Is PJe✚R safe?
PJe+R is high risk. Clicking the AI-assisted search button inserts your judicial query into a prompt for an external AI provider. By default this POSTs to Groq's chat-completions endpoint; it can also target Gemini, OpenAI, Mistral, or OpenRouter.…
Who publishes itConselho Nacional de Justiça - no other listings under this identity, 11 shared hostnames
Conselho Nacional de Justiça - no other listings under this identity, 11 shared hostnames
What this publisher told the store about itself, and the other listings that told it the same thing.
Shared hosts - 11 hostnames
Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Judicial search prompts are sent to external AI APIs
Clicking the AI-assisted search button inserts your judicial query into a prompt for an external AI provider.
By default this POSTs to Groq's chat-completions endpoint; it can also target Gemini, OpenAI, Mistral, or OpenRouter.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You click the AI generation button in the judicial search helper.
The button passes the text area's trimmed value into the AI query generator.
The extension sends a prompt containing that text to an external AI completion API.
The default provider is Groq, and the same provider table also lists Google Gemini, OpenAI, Mistral, and OpenRouter.
- Your typed search requestFind recent decisions about benefit denial (illustrative)
This is the exact natural-language request you entered for the AI-assisted search feature.
- Judicial-search instructionsUse E / AND, OU / OR, !, parentheses, exact phrases, fuzzy search, wildcards, and process-number guidance.
The prompt tells the AI how to convert your request into the extension's advanced search syntax.
- Case-list context in promptPolo Ativo, Polo Passivo, Assunto, Classe, Orgao Julgador, and process-number patterns.
The prompt describes the judicial fields your search may refer to, including parties, subject, class, court body, and judging unit.
- Selected AI providerGroq llama-3.1-8b-instant at https://api.groq.com/openai/v1/chat/completions
This determines which external service receives the generated prompt.
No live request body was recorded during dynamic analysis; static verification confirmed this method and URL in the extension's AI search code path.
- Content-Type
- application/json
- Authorization
- Bearer <redacted>
The AI search feature puts your text into a provider request
Provider table and default provider selection
content/index.global.jsconst PROVEDORES = { groq: { nome: "Groq", url: "https://api.groq.com/openai/v1/chat/completions", modelo: "llama-3.1-8b-instant", descricao: "Rapido e gratuito (14.4k req/dia)", linkCadastro: "https://console.groq.com/keys" }, google: { nome: "Google AI Studio", url: "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent", modelo: "gemini-2.0-flash", descricao: "Gratuito e de alta qualidade (recomendado)", linkCadastro: "https://aistudio.google.com/app/apikey" }, mistral: { nome: "Mistral AI", url: "https://api.mistral.ai/v1/chat/completions", modelo: "mistral-small-latest", descricao: "Gratuito com bom desempenho", linkCadastro: "https://console.mistral.ai/api-keys" }, openai: { nome: "OpenAI", url: "https://api.openai.com/v1/chat/completions", modelo: "gpt-4o-mini", descricao: "Alta qualidade (pago)", linkCadastro: "https://platform.openai.com/api-keys" }, openrouter: { nome: "OpenRouter", url: "https://openrouter.ai/api/v1/chat/completions", modelo: "meta-llama/llama-3.1-8b-instruct:free", descricao: "Varios modelos gratuitos", linkCadastro: "https://openrouter.ai/keys" }};const STORAGE_KEY = "painelGerencialAssistenteIAConfig";const API_KEY_PADRAO = "<redacted>";gerarQuery creates the POST body and sends it through Endpoint.fetch
content/index.global.jsasync gerarQuery(userText, promptText) { if (this.config == null) this.config = await this.carregarConfig(); if (!userText.trim()) return { sucesso: false, erro: "Descricao vazia" }; const apiKey = this.config.apiKeyPersonalizada || (this.config.usarApiPadrao ? API_KEY_PADRAO : ""); if (!apiKey) return { sucesso: false, erro: "Nenhuma API key configurada" }; const provider = PROVEDORES[this.config.provedorSelecionado]; let url = provider.url; let payload; const headers = { "Content-Type": "application/json" }; if (this.config.provedorSelecionado === "google") { url = `${provider.url}?key=${apiKey}`; payload = { contents: [{ parts: [{ text: promptText }] }], generationConfig: { temperature: 0.1, maxOutputTokens: 1000 } }; } else { headers.Authorization = `Bearer ${apiKey}`; if (this.config.provedorSelecionado === "openrouter") { headers["HTTP-Referer"] = window.location.origin; headers["X-Title"] = "PJe+R - Assistente de Busca"; } payload = { model: provider.modelo, messages: [{ role: "user", content: promptText }], temperature: 0.1, max_tokens: 2000 }; } const response = await Endpoint.fetch("obterDoURLComFetchResponse", url, { method: "POST", headers, body: JSON.stringify(payload) }); return response;}gerarQueryComIA passes the typed value into the prompt builder
content/index.global.jsbo.addEventListener("click", async (event) => { event.stopPropagation(); await this.gerarQueryComIA(vo.value.trim(), bo, vo);});async gerarQueryComIA(userText, button, textarea) { const prompt = this.assistenteIA.obterTemplatePrompt(userText); const result = await this.assistenteIA.gerarQuery(userText, prompt); if (result.sucesso && result.query) { this.onQueryGerada && this.onQueryGerada(result.query); textarea.value = ""; }}The background worker performs the routed fetch
obterDoURLComFetchResponse returns the serialized HTTP response
background/index-25zumi8C.mjsasync function fetchThroughBackground(url, options, context) { return fetch(url, options, context);}async function serializeResponse(response) { const cloned = response.clone(); const body = tryParseJson(await cloned.text()); return { ok: response.ok, status: response.status, statusText: response.statusText, url: response.url, body, headers: Object.fromEntries(response.headers.entries()), type: response.type, redirected: response.redirected };}async function obterDoURLComFetchResponse(url, options, context) { const result = await fetchThroughBackground(url, options, context); return result instanceof Response ? await serializeResponse(result) : result;}The endpoints message handler calls Zs.fetch with the requested function name and args
background/index-25zumi8C.mjsyr("endpoints", async ({ data, sender }) => { switch (data.chamar) { case "backgroundFetchEndpoint": { if (!data.opcoes || !data.opcoes.functionName || !data.opcoes.args) { return { backgroundResponseWithError: true, errorMessage: "Requisicao mal formada" }; } if (!Array.isArray(data.opcoes.args)) { return { backgroundResponseWithError: true, errorMessage: "Os argumentos da requisicao devem ser um array" }; } data.opcoes.args.push(`tab-${sender.tabId}`); const result = await Zs.fetch(data.opcoes.functionName, ...data.opcoes.args); return result instanceof Response ? await serializeExtensionResponse(result) : result; } default: return { backgroundResponseWithError: true, errorMessage: "Requisicao desconhecida" }; }});- api.groq.com
Default Groq chat-completions endpoint for the generated judicial-search prompt.
- generativelanguage.googleapis.com
Google Gemini endpoint listed as an alternate provider in the same provider table.
- api.openai.com
OpenAI chat-completions endpoint listed as an alternate provider.
- api.mistral.ai
Mistral chat-completions endpoint listed as an alternate provider.
- openrouter.ai
OpenRouter chat-completions endpoint listed as an alternate provider.