Configuração Hardcoded.
Assistentes de IA incorporam valores específicos de ambiente — URLs, portas, caminhos, timeouts, chaves e números mágicos — diretamente na lógica, em vez de lê-los a partir de configuração ou do ambiente, porque um literal é o próximo token mais provável e o modelo desconhece sua camada de configuração existente.
##Signs and Symptoms
Um assistente de IA tende a emitir um literal plausível exatamente onde deveria haver uma referência. O código roda na demonstração, então o smell sobrevive à revisão a menos que você o procure.
Sinais reveladores:
- Endpoints, portas, caminhos e timeouts inline espalhados pela lógica de negócio em vez de um módulo de configuração:
http://localhost:3000,/tmp/cache,5432,setTimeout(..., 30000). - Números/strings mágicos sem uma constante nomeada — contagens de retentativa, tamanhos de página, limites de taxa, limiares de funcionalidades.
- O mesmo literal repetido em vários arquivos porque o modelo o regenerou em vez de importar uma constante existente (o padrão "copia/cola para cima, refatora para baixo" da GitClear em miniatura).
- Credenciais / chaves hardcoded — tokens de API, chaves de criptografia ou strings de autenticação
Basiccoladas dos dados de treinamento. - Um
config.ts/.env/ objeto de configurações já existente que o novo código ignora por completo. - Valores fixados por ambiente: uma URL de dev/staging ou ID de conta de teste fixado em um caminho que vai para produção.
// 🚩 Gerado por IA: cada parâmetro é um literal, valores de dev embutidos
export async function syncOrders() {
const res = await fetch("https://api.staging.acme.dev/v1/orders", {
headers: { Authorization: "Bearer sk_test_4eC39HqLyjWDarjtT1zdp7dc" },
signal: AbortSignal.timeout(30000),
});
const orders = (await res.json()).slice(0, 50); // por que 50?
for (let i = 0; i < 3; i++) { /* tenta novamente 3x... por que 3? */ }
}
A linha Authorization é um alerta do gitleaks/Semgrep; a URL, 30000, 50 e 3 são smells de valores mágicos; e api.staging.acme.dev é um valor de dev prestes a chegar à produção.
##Reasons for the Problem
Por que os modelos produzem isso
- Um literal é o token seguinte de maior probabilidade. Dado
fetch(, a conclusão mais barata que satisfaz o prompt imediato é uma string de URL concreta, nãoconfig.apiBaseUrl. Resolver uma referência exige saber que um símbolo existe em outro lugar; emitir um valor não exige nada. Os modelos otimizam para um trecho localmente plausível e executável. - O corpus de treinamento é composto de trechos autocontidos. Tutoriais, exemplos de README e respostas do Stack Overflow embutem seus valores para que rodem de forma independente. O modelo aprendeu que "bom código de exemplo" usa hardcode — o oposto da higiene de produção.
- Sem contexto do repositório / janela limitada. Normalmente o modelo não leu seu
config/, o schema de env ou o arquivo de constantes, então não consegue reutilizá-los. A GitClear associa exatamente isso ao aumento da duplicação: os assistentes têm "menor probabilidade de propor a reutilização de uma função semelhante… em parte por causa do tamanho limitado do contexto", com blocos duplicados de mais de 5 linhas crescendo cerca de 8× em 2024, enquanto as linhas refatoradas ("movidas") caíram de ~24% para ~9,5%. - Bajulação / viés de responder ao prompt. Quando solicitado a "adicionar uma sincronização de pedidos", o modelo entrega algo que funciona agora; externalizar a configuração é um esforço adicional que ele não fará por conta própria a menos que seja instruído.
- Defasagem do corte de treinamento. Literais embutidos costumam ser literais desatualizados — endpoints antigos, versões de API descontinuadas, portas padrão ou constantes criptográficas fracas (MD5, chaves hardcoded). A OX Security descobriu que 62% do código gerado por IA é entregue com problemas e atribui chaves/segredos/caminhos hardcoded a padrões "aprendidos de bases de código legadas… [com] zero consciência de que os padrões de segurança evoluíram."
Por que isso prejudica
- Manutenibilidade — Shotgun Surgery. Mudar um único timeout ou URL base significa caçar cada literal duplicado por toda a base de código; se esquecer um, o comportamento diverge silenciosamente em cada ponto de chamada.
- Correção entre ambientes. Uma URL de staging ou um ID de conta de dev fixado na lógica acaba indo para produção; limiares mágicos sem nome ficam fora de sincronia com os valores que deveriam refletir.
- Segurança. Tokens/chaves hardcoded são vazamentos de credenciais — uma vez commitados, vivem para sempre no histórico do git. O estudo de código de build do arXiv (2601.16839) encontrou caminhos/URLs hardcoded e credenciais hardcoded de alta severidade recorrentes em arquivos de build gerados por IA.
- Carga de revisão & dívida técnica. Os revisores precisam verificar a procedência de cada literal. O trabalho sobre smells específicos de IA (arXiv 2509.20491) observa que os modelos lidam bem com "literais dentro do escopo", mas têm dificuldade com casos sensíveis a valores, em que a correção depende de limiares que se propagam por funções auxiliares — exatamente os valores hardcoded que os humanos agora têm que auditar à mão. Segundo o Q&A do Stack Overflow com Eno Reyes, da Factory, a qualidade de base do código é "o único sinal" para saber se os agentes aceleram ou desaceleram uma equipe — e o espalhamento de valores hardcoded corrói exatamente essa base.
##Treatment
Táticas de prompting / revisão
- Aponte o modelo para sua superfície de configuração: "Leia
src/config.tse.env.example; useconfig.*/process.envpara cada URL, porta, timeout e credencial. Não introduza literais." Os modelos usam literais inline porque não sabem que o símbolo existe — nomeie-o. - Proíba valores mágicos explicitamente: "Sem números ou strings mágicos — extraia constantes nomeadas." Depois, faça-o rodar
eslint --rule no-magic-numberse um scanner de segredos (gitleaks/Semgrep) e corrija o que eles sinalizarem. Conforme a orientação da Factory, integre linters/scanners ao loop para que o agente se autocorrija em vez de depender da revisão humana. - Forneça o schema de env (zod/envalid/
.env.example) para que o modelo tenha onde colocar os valores em vez de adivinhá-los. - Faça grep nos novos diffs em busca de
http,localhost, literais de IP,Bearere dígitos soltos em argumentos de chamada antes de fazer o merge.
A refatoração — nomeie os movimentos clássicos:
- Substituir Número Mágico por Constante Simbólica para limiares, contagens, tamanhos.
- Extrair Função / Extrair Módulo de Configuração para reunir os parâmetros em um único lugar tipado e validado.
- Externalizar para o Ambiente (12-factor) para tudo que difere por ambiente ou é secreto; nunca commite segredos.
// config.ts — fonte única e validada da verdade
import { z } from "zod";
const env = z.object({
ORDERS_API_BASE_URL: z.string().url(),
ORDERS_API_TOKEN: z.string().min(1),
ORDERS_TIMEOUT_MS: z.coerce.number().default(30_000),
ORDERS_PAGE_SIZE: z.coerce.number().default(50),
ORDERS_MAX_RETRIES: z.coerce.number().default(3),
}).parse(process.env);
export const config = env;
// ✅ depois: referências, não literais — um único lugar para alterar, segredo fora do código-fonte
import { config } from "./config";
export async function syncOrders() {
const res = await fetch(`${config.ORDERS_API_BASE_URL}/v1/orders`, {
headers: { Authorization: `Bearer ${config.ORDERS_API_TOKEN}` },
signal: AbortSignal.timeout(config.ORDERS_TIMEOUT_MS),
});
const orders = (await res.json()).slice(0, config.ORDERS_PAGE_SIZE);
for (let i = 0; i < config.ORDERS_MAX_RETRIES; i++) { /* ... */ }
}
Se um segredo já foi parar em um commit, rotacione-o — remover a linha não apaga o histórico do git.
##Detected by
- ESLint no-magic-numbers — Proibir números mágicos
- SonarSource typescript:S109 / java:S109 — "Magic numbers should not be used" — Números mágicos
- SonarSource java:S1075 — "URIs should not be hardcoded" — URIs hardcoded
- SonarSource java:S2068 — "Hard-coded credentials are security-sensitive" — Credenciais hardcoded
- Checkstyle MagicNumber — Verificação de número mágico
- PMD AvoidUsingHardCodedIP — Evitar endereços IP hardcoded
- Bandit B105 hardcoded_password_string / B108 hardcoded_tmp_directory — Senhas hardcoded / diretórios temporários (Python)
- gitleaks secret detection (e.g. generic-api-key, regex/entropy rules) — Scanner de segredos hardcoded
- Semgrep generic.secrets / hardcoded-credentials registry rules — Regras de segredos/configuração hardcoded
- eslint-plugin-no-secrets no-secrets/no-secrets — Detecção de strings de alta entropia (segredos)