[{"data":1,"prerenderedAt":1137},["ShallowReactive",2],{"biblioteca-\u002Fbiblioteca\u002Fguarda-tus-tokens-sin-filtrarlos":3},{"id":4,"title":5,"author":6,"body":7,"cover":1122,"description":1123,"extension":1124,"meta":1125,"navigation":344,"nivel":1126,"path":1127,"publishedAt":1128,"seo":1129,"stem":1130,"tags":1131,"__hash__":1136},"biblioteca\u002Fbiblioteca\u002Fguarda-tus-tokens-sin-filtrarlos.md","No uses .env, tu computador ya tiene caja fuerte","Miguel Santa",{"type":8,"value":9,"toc":1105},"minimark",[10,28,33,44,81,84,89,96,100,103,113,117,131,134,137,143,146,149,153,160,168,173,175,179,182,214,216,220,230,233,236,249,251,255,262,324,391,418,428,430,434,444,468,537,543,545,552,559,605,647,693,695,699,702,779,781,785,792,798,810,866,877,899,901,905,908,911,943,1054,1060,1062,1066,1090,1101],[11,12,15,19,25],"callout",{"title":13,"type":14},"¿Apurado? Que Claude te haga un resumen rápido.","claude",[16,17,18],"p",{},"Copia el link de esta página y pégalo en Claude (claude.ai, el escritorio o la app). Le pides:",[16,20,21],{},[22,23,24],"strong",{},"\"Resúmeme esta guía y dime exactamente qué tengo que hacer hoy con mis API keys.\"",[16,26,27],{},"En 30 segundos tienes lo importante. Si te interesa profundo, te devuelves a la sección que te llame.",[29,30,32],"h2",{"id":31},"primero-qué-es-un-token-y-por-qué-tanto-cuidado","Primero · ¿Qué es un token y por qué tanto cuidado?",[16,34,35,36,39,40,43],{},"Si acabas de empezar a programar con IA, probablemente escuchaste la palabra ",[22,37,38],{},"\"token\""," o ",[22,41,42],{},"\"API key\""," y todavía no te queda del todo claro qué es. Vamos por ahí.",[11,45,48,59],{"title":46,"type":47},"Una metáfora simple","info",[16,49,50,51,54,55,58],{},"Un ",[22,52,53],{},"token"," es como la ",[22,56,57],{},"llave magnética de un hotel",".",[60,61,62,66,69,75],"ul",{},[63,64,65],"li",{},"Te identifica frente a un servicio (OpenAI, Stripe, Anthropic, etc.).",[63,67,68],{},"Te abre el acceso a usar ese servicio.",[63,70,71,72,58],{},"Mientras la llave esté activa, ",[22,73,74],{},"cualquiera que la tenga puede usarla como si fuera tú",[63,76,77,78,58],{},"Y cualquier consumo se cobra a ",[22,79,80],{},"tu cuenta",[16,82,83],{},"Por eso importa guardarla bien. No es paranoia. Es responsabilidad básica.",[85,86,88],"h3",{"id":87},"lo-que-pasa-cuando-una-llave-se-filtra","Lo que pasa cuando una llave se filtra",[16,90,91,92,95],{},"Esto no es teoría. Son números de un reporte público de ",[22,93,94],{},"GitGuardian"," (empresa de ciberseguridad que escanea GitHub a diario):",[97,98],"stat-grid",{":items":99},"[{\"value\":\"12,7M\",\"label\":\"secretos filtrados\",\"caption\":\"en GitHub público durante 2023\",\"accent\":true},{\"value\":\"+28%\",\"label\":\"crecimiento anual\",\"caption\":\"se multiplican cada año\"},{\"value\":\"1.212×\",\"label\":\"API keys de OpenAI\",\"caption\":\"crecimiento en un solo año (2022→2023)\"}]",[16,101,102],{},"Y este es el dato que más asusta:",[11,104,107],{"title":105,"type":106},"90% de las llaves filtradas siguen activas 5 días después","danger",[16,108,109,110,58],{},"Es decir, el dueño ni siquiera se enteró que estaba expuesta. Los bots automáticos sí. Y mientras tanto, ",[22,111,112],{},"alguien la usa y el consumo se cobra a tu cuenta",[85,114,116],{"id":115},"caso-real-toyota-5-años-expuesto","Caso real · Toyota, 5 años expuesto",[16,118,119,120,123,124,127,128,58],{},"En ",[22,121,122],{},"octubre de 2022, Toyota"," admitió públicamente que un token de acceso a su sistema ",[22,125,126],{},"T-Connect"," (su plataforma conectada de autos) había estado ",[22,129,130],{},"expuesto en GitHub durante 5 años",[16,132,133],{},"Lo había subido por error un subcontratista en un repositorio público. Nadie revisó. Estuvo ahí 1.825 días.",[97,135],{":items":136},"[{\"value\":\"5 años\",\"label\":\"duración de la fuga\",\"caption\":\"entre 2017 y 2022\"},{\"value\":\"296.019\",\"label\":\"clientes afectados\",\"caption\":\"emails + números de cliente expuestos\",\"accent\":true},{\"value\":\"$0\",\"label\":\"valor de un .env\",\"caption\":\"como herramienta de seguridad\"}]",[16,138,139,142],{},[22,140,141],{},"Si le pasa a Toyota, te puede pasar a ti."," La diferencia es que tu llave de OpenAI no es defendida por un equipo de ciberseguridad. Es solo tuya. Si se filtra, tú pagas la cuenta.",[16,144,145],{},"Por eso esta guía existe.",[147,148],"hr",{},[29,150,152],{"id":151},"la-tesis","La tesis",[16,154,155,156,159],{},"Tu Mac, Windows o Linux ya viene con una ",[22,157,158],{},"caja fuerte cifrada",". Está ahí desde el día uno. Casi nadie la usa.",[16,161,162,163,167],{},"En cambio, mucha gente guarda sus llaves de OpenAI, Stripe o Anthropic en un archivo de texto plano llamado ",[164,165,166],"code",{},".env",". Y un buen día se les filtra.",[16,169,170],{},[22,171,172],{},"No vamos a hablar de \"cuándo usar .env\". Vamos a hablar de cómo dejar de usarlo.",[147,174],{},[29,176,178],{"id":177},"_1-las-tres-zonas-donde-puede-vivir-tu-llave","1 · Las tres zonas donde puede vivir tu llave",[180,181],"diagram-donde-viven-llaves",{},[11,183,186,211],{"title":184,"type":185},"La regla es simple","warning",[60,187,188,198,205],{},[63,189,190,191,194,195,197],{},"Nunca la ",[22,192,193],{},"opción 1"," (archivo ",[164,196,166],{}," con valores reales)",[63,199,200,201,204],{},"Siempre la ",[22,202,203],{},"opción 2"," para trabajar en tu máquina",[63,206,200,207,210],{},[22,208,209],{},"opción 3"," para producción",[16,212,213],{},"Lo demás son detalles.",[147,215],{},[29,217,219],{"id":218},"_2-por-qué-un-env-es-peligroso-por-defecto","2 · Por qué un .env es peligroso por defecto",[16,221,222,223,225,226,229],{},"Un archivo ",[164,224,166],{}," es ",[22,227,228],{},"texto plano",". Sin cifrar. Cualquiera con acceso a tu disco lo lee.",[16,231,232],{},"Pero el riesgo real no es ese. El riesgo real es esta cadena:",[234,235],"diagram-flujo-fuga",{},[11,237,239],{"title":238,"type":106},"Lo importante de entender",[16,240,241,242,244,245,248],{},"Aunque borres el ",[164,243,166],{}," del repositorio después, ",[22,246,247],{},"la llave queda en el historial de git para siempre",". Y los bots que escanean GitHub la encuentran en minutos. No en días.",[147,250],{},[29,252,254],{"id":253},"_3-mac-tu-keychain-ya-está-ahí","3 · Mac · Tu Keychain ya está ahí",[16,256,257,258,261],{},"macOS viene con ",[22,259,260],{},"Keychain Access",". Una caja fuerte cifrada con tu contraseña de usuario. La abre tu sistema cuando inicias sesión.",[263,264,267],"step-card",{"number":265,"title":266},"1","Guardar una llave",[268,269,274],"pre",{"className":270,"code":271,"language":272,"meta":273,"style":273},"language-bash shiki shiki-themes github-light github-dark","security add-generic-password \\\n  -a \"santaia\" \\\n  -s \"santaia:openai-key\" \\\n  -w \"sk-proj-tu-llave-real\"\n","bash","",[164,275,276,293,304,315],{"__ignoreMap":273},[277,278,281,285,289],"span",{"class":279,"line":280},"line",1,[277,282,284],{"class":283},"sScJk","security",[277,286,288],{"class":287},"sZZnC"," add-generic-password",[277,290,292],{"class":291},"sj4cs"," \\\n",[277,294,296,299,302],{"class":279,"line":295},2,[277,297,298],{"class":291},"  -a",[277,300,301],{"class":287}," \"santaia\"",[277,303,292],{"class":291},[277,305,307,310,313],{"class":279,"line":306},3,[277,308,309],{"class":291},"  -s",[277,311,312],{"class":287}," \"santaia:openai-key\"",[277,314,292],{"class":291},[277,316,318,321],{"class":279,"line":317},4,[277,319,320],{"class":291},"  -w",[277,322,323],{"class":287}," \"sk-proj-tu-llave-real\"\n",[263,325,328],{"number":326,"title":327},"2","Leerla desde tu código",[268,329,333],{"className":330,"code":331,"language":332,"meta":273,"style":273},"language-python shiki shiki-themes github-light github-dark","import subprocess\n\ndef get_secret(name: str) -> str:\n    return subprocess.run(\n        [\"security\", \"find-generic-password\",\n         \"-s\", name, \"-a\", \"santaia\", \"-w\"],\n        capture_output=True, text=True, check=True\n    ).stdout.strip()\n\nopenai_key = get_secret(\"santaia:openai-key\")\n","python",[164,334,335,340,346,351,356,362,368,374,380,385],{"__ignoreMap":273},[277,336,337],{"class":279,"line":280},[277,338,339],{},"import subprocess\n",[277,341,342],{"class":279,"line":295},[277,343,345],{"emptyLinePlaceholder":344},true,"\n",[277,347,348],{"class":279,"line":306},[277,349,350],{},"def get_secret(name: str) -> str:\n",[277,352,353],{"class":279,"line":317},[277,354,355],{},"    return subprocess.run(\n",[277,357,359],{"class":279,"line":358},5,[277,360,361],{},"        [\"security\", \"find-generic-password\",\n",[277,363,365],{"class":279,"line":364},6,[277,366,367],{},"         \"-s\", name, \"-a\", \"santaia\", \"-w\"],\n",[277,369,371],{"class":279,"line":370},7,[277,372,373],{},"        capture_output=True, text=True, check=True\n",[277,375,377],{"class":279,"line":376},8,[277,378,379],{},"    ).stdout.strip()\n",[277,381,383],{"class":279,"line":382},9,[277,384,345],{"emptyLinePlaceholder":344},[277,386,388],{"class":279,"line":387},10,[277,389,390],{},"openai_key = get_secret(\"santaia:openai-key\")\n",[263,392,395],{"number":393,"title":394},"3","Borrarla si la rotaste",[268,396,398],{"className":270,"code":397,"language":272,"meta":273,"style":273},"security delete-generic-password -s \"santaia:openai-key\" -a \"santaia\"\n",[164,399,400],{"__ignoreMap":273},[277,401,402,404,407,410,412,415],{"class":279,"line":280},[277,403,284],{"class":283},[277,405,406],{"class":287}," delete-generic-password",[277,408,409],{"class":291}," -s",[277,411,312],{"class":287},[277,413,414],{"class":291}," -a",[277,416,417],{"class":287}," \"santaia\"\n",[11,419,422],{"title":420,"type":421},"Listo","success",[16,423,424,425],{},"Tu llave vive en una caja fuerte cifrada. Tu código la lee solo cuando la necesita. ",[22,426,427],{},"Nada en disco como texto plano.",[147,429],{},[29,431,433],{"id":432},"_4-windows-credential-manager","4 · Windows · Credential Manager",[16,435,436,437,440,441,58],{},"Windows también lo tiene. Se llama ",[22,438,439],{},"Credential Manager"," y se maneja desde PowerShell con ",[164,442,443],{},"cmdkey",[263,445,446],{"number":265,"title":266},[268,447,451],{"className":448,"code":449,"language":450,"meta":273,"style":273},"language-powershell shiki shiki-themes github-light github-dark","cmdkey \u002Fgeneric:\"santaia:openai-key\" `\n       \u002Fuser:\"santaia\" `\n       \u002Fpass:\"sk-proj-tu-llave-real\"\n","powershell",[164,452,453,458,463],{"__ignoreMap":273},[277,454,455],{"class":279,"line":280},[277,456,457],{},"cmdkey \u002Fgeneric:\"santaia:openai-key\" `\n",[277,459,460],{"class":279,"line":295},[277,461,462],{},"       \u002Fuser:\"santaia\" `\n",[277,464,465],{"class":279,"line":306},[277,466,467],{},"       \u002Fpass:\"sk-proj-tu-llave-real\"\n",[263,469,470,477,486,489],{"number":326,"title":327},[16,471,472,473,476],{},"Necesitas el módulo ",[164,474,475],{},"CredentialManager"," (una sola vez):",[268,478,480],{"className":448,"code":479,"language":450,"meta":273,"style":273},"Install-Module -Name CredentialManager -Scope CurrentUser\n",[164,481,482],{"__ignoreMap":273},[277,483,484],{"class":279,"line":280},[277,485,479],{},[16,487,488],{},"Después desde Python:",[268,490,492],{"className":330,"code":491,"language":332,"meta":273,"style":273},"import subprocess\n\ndef get_secret(target: str) -> str:\n    ps = f'(Get-StoredCredential -Target \"{target}\").GetNetworkCredential().Password'\n    return subprocess.run(\n        [\"powershell\", \"-Command\", ps],\n        capture_output=True, text=True, check=True\n    ).stdout.strip()\n\nopenai_key = get_secret(\"santaia:openai-key\")\n",[164,493,494,498,502,507,512,516,521,525,529,533],{"__ignoreMap":273},[277,495,496],{"class":279,"line":280},[277,497,339],{},[277,499,500],{"class":279,"line":295},[277,501,345],{"emptyLinePlaceholder":344},[277,503,504],{"class":279,"line":306},[277,505,506],{},"def get_secret(target: str) -> str:\n",[277,508,509],{"class":279,"line":317},[277,510,511],{},"    ps = f'(Get-StoredCredential -Target \"{target}\").GetNetworkCredential().Password'\n",[277,513,514],{"class":279,"line":358},[277,515,355],{},[277,517,518],{"class":279,"line":364},[277,519,520],{},"        [\"powershell\", \"-Command\", ps],\n",[277,522,523],{"class":279,"line":370},[277,524,373],{},[277,526,527],{"class":279,"line":376},[277,528,379],{},[277,530,531],{"class":279,"line":382},[277,532,345],{"emptyLinePlaceholder":344},[277,534,535],{"class":279,"line":387},[277,536,390],{},[11,538,540],{"title":539,"type":47},"Si usas WSL",[16,541,542],{},"Si en Windows trabajas dentro de WSL (Linux dentro de Windows), salta a la siguiente sección. Te aplica esa.",[147,544],{},[29,546,548,549],{"id":547},"_5-linux-secret-tool","5 · Linux · ",[164,550,551],{},"secret-tool",[16,553,554,555,558],{},"Linux usa ",[22,556,557],{},"libsecret"," como API estándar. Instala la CLI una vez:",[268,560,562],{"className":270,"code":561,"language":272,"meta":273,"style":273},"# Debian \u002F Ubuntu\nsudo apt install libsecret-tools\n\n# Fedora\nsudo dnf install libsecret\n",[164,563,564,570,584,588,593],{"__ignoreMap":273},[277,565,566],{"class":279,"line":280},[277,567,569],{"class":568},"sJ8bj","# Debian \u002F Ubuntu\n",[277,571,572,575,578,581],{"class":279,"line":295},[277,573,574],{"class":283},"sudo",[277,576,577],{"class":287}," apt",[277,579,580],{"class":287}," install",[277,582,583],{"class":287}," libsecret-tools\n",[277,585,586],{"class":279,"line":306},[277,587,345],{"emptyLinePlaceholder":344},[277,589,590],{"class":279,"line":317},[277,591,592],{"class":568},"# Fedora\n",[277,594,595,597,600,602],{"class":279,"line":358},[277,596,574],{"class":283},[277,598,599],{"class":287}," dnf",[277,601,580],{"class":287},[277,603,604],{"class":287}," libsecret\n",[263,606,607,644],{"number":265,"title":266},[268,608,610],{"className":270,"code":609,"language":272,"meta":273,"style":273},"secret-tool store --label=\"OpenAI · santaia\" \\\n  service \"santaia\" \\\n  key \"openai-key\"\n",[164,611,612,627,636],{"__ignoreMap":273},[277,613,614,616,619,622,625],{"class":279,"line":280},[277,615,551],{"class":283},[277,617,618],{"class":287}," store",[277,620,621],{"class":291}," --label=",[277,623,624],{"class":287},"\"OpenAI · santaia\"",[277,626,292],{"class":291},[277,628,629,632,634],{"class":279,"line":295},[277,630,631],{"class":287},"  service",[277,633,301],{"class":287},[277,635,292],{"class":291},[277,637,638,641],{"class":279,"line":306},[277,639,640],{"class":287},"  key",[277,642,643],{"class":287}," \"openai-key\"\n",[16,645,646],{},"Te pregunta el valor de la llave en interactivo. No queda en tu historial de bash.",[263,648,649],{"number":326,"title":327},[268,650,652],{"className":330,"code":651,"language":332,"meta":273,"style":273},"import subprocess\n\ndef get_secret(service: str, key: str) -> str:\n    return subprocess.run(\n        [\"secret-tool\", \"lookup\", \"service\", service, \"key\", key],\n        capture_output=True, text=True, check=True\n    ).stdout.strip()\n\nopenai_key = get_secret(\"santaia\", \"openai-key\")\n",[164,653,654,658,662,667,671,676,680,684,688],{"__ignoreMap":273},[277,655,656],{"class":279,"line":280},[277,657,339],{},[277,659,660],{"class":279,"line":295},[277,661,345],{"emptyLinePlaceholder":344},[277,663,664],{"class":279,"line":306},[277,665,666],{},"def get_secret(service: str, key: str) -> str:\n",[277,668,669],{"class":279,"line":317},[277,670,355],{},[277,672,673],{"class":279,"line":358},[277,674,675],{},"        [\"secret-tool\", \"lookup\", \"service\", service, \"key\", key],\n",[277,677,678],{"class":279,"line":364},[277,679,373],{},[277,681,682],{"class":279,"line":370},[277,683,379],{},[277,685,686],{"class":279,"line":376},[277,687,345],{"emptyLinePlaceholder":344},[277,689,690],{"class":279,"line":382},[277,691,692],{},"openai_key = get_secret(\"santaia\", \"openai-key\")\n",[147,694],{},[29,696,698],{"id":697},"_6-mi-convención-de-naming","6 · Mi convención de naming",[16,700,701],{},"Cuando llevas 30+ llaves entre varios proyectos, sin convención no encuentras nada. Esta es la que uso:",[703,704,709,735],"compare-grid",{"bad-label":705,"bad-title":706,"good-label":707,"good-title":708},"Para llaves globales","patrón: servicio-contexto","Para llaves de un proyecto","patrón: proyecto:servicio",[710,711,712,729],"template",{"v-slot:bad":273},[60,713,714,719,724],{},[63,715,716],{},[164,717,718],{},"gitlab-terracomerce",[63,720,721],{},[164,722,723],{},"gitlab-personal",[63,725,726],{},[164,727,728],{},"anthropic-personal",[16,730,731,732,58],{},"Llaves que usas en varios proyectos. El sufijo dice ",[22,733,734],{},"para qué cuenta",[710,736,737,754,757],{"v-slot:good":273},[60,738,739,744,749],{},[63,740,741],{},[164,742,743],{},"santaia:openai-key",[63,745,746],{},[164,747,748],{},"santaia:elevenlabs-key",[63,750,751],{},[164,752,753],{},"santaia:gemini-key",[16,755,756],{},"Llaves específicas de un proyecto. Los dos puntos separan el proyecto del servicio. Fácil de filtrar:",[268,758,760],{"className":270,"code":759,"language":272,"meta":273,"style":273},"security dump-keychain | grep santaia\n",[164,761,762],{"__ignoreMap":273},[277,763,764,766,769,773,776],{"class":279,"line":280},[277,765,284],{"class":283},[277,767,768],{"class":287}," dump-keychain",[277,770,772],{"class":771},"szBVR"," |",[277,774,775],{"class":283}," grep",[277,777,778],{"class":287}," santaia\n",[147,780],{},[29,782,784],{"id":783},"_7-producción-nunca-en-tu-máquina","7 · Producción · Nunca en tu máquina",[16,786,787,788,791],{},"Tu computador personal ",[22,789,790],{},"nunca"," debe tener llaves de producción. Punto.",[16,793,794,795,58],{},"Las llaves de producción viven en el panel del proveedor donde despliegas. Se inyectan ",[22,796,797],{},"solo cuando se ejecuta el build",[263,799,801,807],{"number":265,"title":800},"Cloudflare Pages",[16,802,803,806],{},[22,804,805],{},"Ruta:"," Settings → Environment variables → Add",[16,808,809],{},"Pones nombre + valor + ambiente (Production \u002F Preview). Guardas y redeploy. La variable solo existe durante el build.",[263,811,813,818,825],{"number":326,"title":812},"GitHub Actions",[16,814,815,817],{},[22,816,805],{}," Settings → Secrets and variables → Actions → New repository secret",[16,819,820,821,824],{},"En tu workflow lo lees con ",[164,822,823],{},"secrets.NOMBRE",":",[268,826,830],{"className":827,"code":828,"language":829,"meta":273,"style":273},"language-yaml shiki shiki-themes github-light github-dark","- env:\n    OPENAI_KEY: ${{ secrets.OPENAI_KEY }}\n  run: npm run deploy\n","yaml",[164,831,832,845,856],{"__ignoreMap":273},[277,833,834,838,842],{"class":279,"line":280},[277,835,837],{"class":836},"sVt8B","- ",[277,839,841],{"class":840},"s9eBZ","env",[277,843,844],{"class":836},":\n",[277,846,847,850,853],{"class":279,"line":295},[277,848,849],{"class":840},"    OPENAI_KEY",[277,851,852],{"class":836},": ",[277,854,855],{"class":287},"${{ secrets.OPENAI_KEY }}\n",[277,857,858,861,863],{"class":279,"line":306},[277,859,860],{"class":840},"  run",[277,862,852],{"class":836},[277,864,865],{"class":287},"npm run deploy\n",[263,867,869,874],{"number":393,"title":868},"GitLab CI\u002FCD",[16,870,871,873],{},[22,872,805],{}," Settings → CI\u002FCD → Variables → Add variable",[16,875,876],{},"Marca la variable como \"Masked\" para que no aparezca en los logs. Se inyecta sola cuando corre el pipeline.",[263,878,881,886],{"number":879,"title":880},"4","Railway",[16,882,883,885],{},[22,884,805],{}," pestaña Variables de cada servicio",[16,887,888,889,891,892,895,896,898],{},"Puedes importar de un ",[164,890,166],{}," local en bloque. Esa es la ",[22,893,894],{},"única vez"," que un ",[164,897,166],{}," tiene sentido: importarlo a Railway una vez y nunca más.",[147,900],{},[29,902,904],{"id":903},"_8-y-si-ya-filtré-algo","8 · ¿Y si ya filtré algo?",[16,906,907],{},"Te puede pasar. Si pasó, no entres en pánico. Tres pasos en orden:",[909,910],"diagram-rotacion-llave",{},[263,912,914,920,940],{"number":265,"title":913},"Rota la llave en el servicio",[16,915,916,919],{},[22,917,918],{},"Esto primero."," Mientras la llave vieja siga activa, el daño sigue creciendo.",[60,921,922,928,934],{},[63,923,924,927],{},[22,925,926],{},"OpenAI:"," Dashboard → API Keys → Revoke → crea nueva",[63,929,930,933],{},[22,931,932],{},"Stripe:"," Dashboard → Developers → API keys → Roll",[63,935,936,939],{},[22,937,938],{},"AWS:"," IAM → Access Keys → Deactivate + Delete + Create new",[16,941,942],{},"Cualquier servicio serio tiene un botón de \"rotate\" o \"revoke\" en su panel.",[263,944,946,949,1002,1008,1048],{"number":326,"title":945},"Limpia el historial de git",[16,947,948],{},"Para repos privados y recientes, basta con:",[268,950,952],{"className":270,"code":951,"language":272,"meta":273,"style":273},"git rm --cached .env\necho \".env\" >> .gitignore\ngit commit -m \"chore: remove .env from tracking\"\ngit push\n",[164,953,954,968,982,995],{"__ignoreMap":273},[277,955,956,959,962,965],{"class":279,"line":280},[277,957,958],{"class":283},"git",[277,960,961],{"class":287}," rm",[277,963,964],{"class":291}," --cached",[277,966,967],{"class":287}," .env\n",[277,969,970,973,976,979],{"class":279,"line":295},[277,971,972],{"class":291},"echo",[277,974,975],{"class":287}," \".env\"",[277,977,978],{"class":771}," >>",[277,980,981],{"class":287}," .gitignore\n",[277,983,984,986,989,992],{"class":279,"line":306},[277,985,958],{"class":283},[277,987,988],{"class":287}," commit",[277,990,991],{"class":291}," -m",[277,993,994],{"class":287}," \"chore: remove .env from tracking\"\n",[277,996,997,999],{"class":279,"line":317},[277,998,958],{"class":283},[277,1000,1001],{"class":287}," push\n",[16,1003,1004,1005,824],{},"Para repos públicos o historiales largos, usa ",[164,1006,1007],{},"git-filter-repo",[268,1009,1011],{"className":270,"code":1010,"language":272,"meta":273,"style":273},"pip install git-filter-repo\ngit filter-repo --invert-paths --path .env\ngit push --force\n",[164,1012,1013,1023,1038],{"__ignoreMap":273},[277,1014,1015,1018,1020],{"class":279,"line":280},[277,1016,1017],{"class":283},"pip",[277,1019,580],{"class":287},[277,1021,1022],{"class":287}," git-filter-repo\n",[277,1024,1025,1027,1030,1033,1036],{"class":279,"line":295},[277,1026,958],{"class":283},[277,1028,1029],{"class":287}," filter-repo",[277,1031,1032],{"class":291}," --invert-paths",[277,1034,1035],{"class":291}," --path",[277,1037,967],{"class":287},[277,1039,1040,1042,1045],{"class":279,"line":306},[277,1041,958],{"class":283},[277,1043,1044],{"class":287}," push",[277,1046,1047],{"class":291}," --force\n",[11,1049,1051],{"title":1050,"type":185},"Avisa a tu equipo antes del --force",[16,1052,1053],{},"Todos los que tengan el repo clonado van a tener que re-clonarlo. Coordina antes, no después.",[263,1055,1057],{"number":393,"title":1056},"Anota qué pasó",[16,1058,1059],{},"En el README o tu sistema de notas: qué llave se filtró, qué hiciste, qué falló en tu proceso. Sin esto, el segundo incidente cae igual.",[147,1061],{},[29,1063,1065],{"id":1064},"cierre","Cierre",[11,1067,1069],{"title":1068,"type":421},"Las 3 reglas que tienes que recordar",[1070,1071,1072,1078,1084],"ol",{},[63,1073,1074,1077],{},[22,1075,1076],{},"Nunca llaves reales en .env."," Es texto plano. Se filtra fácil.",[63,1079,1080,1083],{},[22,1081,1082],{},"Local en el gestor del sistema."," Mac → Keychain. Windows → Credential Manager. Linux → libsecret.",[63,1085,1086,1089],{},[22,1087,1088],{},"Producción en el panel del proveedor."," Tu máquina no las conoce.",[16,1091,1092,1093,1100],{},"Si pruebas esto en algún proyecto tuyo y se te traba algo, escríbeme en ",[1094,1095,1099],"a",{"href":1096,"rel":1097},"https:\u002F\u002Finstagram.com\u002Fsantaia.lab",[1098],"nofollow","@santaia.lab",". Las dudas reales son el material del próximo artículo.",[1102,1103,1104],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":273,"searchDepth":295,"depth":295,"links":1106},[1107,1111,1112,1113,1114,1115,1116,1118,1119,1120,1121],{"id":31,"depth":295,"text":32,"children":1108},[1109,1110],{"id":87,"depth":306,"text":88},{"id":115,"depth":306,"text":116},{"id":151,"depth":295,"text":152},{"id":177,"depth":295,"text":178},{"id":218,"depth":295,"text":219},{"id":253,"depth":295,"text":254},{"id":432,"depth":295,"text":433},{"id":547,"depth":295,"text":1117},"5 · Linux · secret-tool",{"id":697,"depth":295,"text":698},{"id":783,"depth":295,"text":784},{"id":903,"depth":295,"text":904},{"id":1064,"depth":295,"text":1065},null,"Tu sistema operativo ya viene con un gestor de claves cifrado. La mayoría no lo usa y arriesga sus API keys en un .env. Te muestro cómo cambiar el hábito en 5 minutos.","md",{},"intermedio","\u002Fbiblioteca\u002Fguarda-tus-tokens-sin-filtrarlos","2026-05-13",{"title":5,"description":1123},"biblioteca\u002Fguarda-tus-tokens-sin-filtrarlos",[1132,1133,1134,841,1135],"seguridad","tokens","keychain","secretos","ocef-siS8uaY1YHfbKMzVUH_Xabx_7hz59HhUWXwmLc",1791391287456]