Ctrl K
ComunidadGuías…

uncommit-keys.bat

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
@echo off
setlocal EnableDelayedExpansion
REM ============================================================================
REM  uncommit-keys.bat  -  Angela's secret-leak seatbelt for the Tlamatini repo.
REM  Created for Angela Lopez Mendoza (@angelahack1), creator of Tlamatini.
REM
REM  THE FREQUENT MISTAKE THIS CATCHES
REM  ---------------------------------
REM  config.json and 8 agent config.yaml files are TRACKED, and your local copies
REM  legitimately hold REAL keys (keyed mode, from data.keys). GitHub's copy holds
REM  "<KEY goes here>" placeholders (push-able mode). Those files are SUPPOSED to
REM  sit permanently "modified" in git status. A `git add -A` / `git commit -a`
REM  sweeps them into a commit -> real keys committed.
REM
REM  HOW IT DETECTS IT
REM  -----------------
REM  It counts "goes here" placeholders in each secret file and compares your blob
REM  against the upstream blob. FEWER placeholders than upstream = real keys leaked
REM  in. This auto-adapts when you add a new key (no hardcoded counts to maintain).
REM
REM  SAFETY CONTRACT (matches CLAUDE.md's PRIVATE DATA GUARD)
REM  --------------------------------------------------------
REM    * Only ever touches UNPUSHED, local-only commits.
REM    * REFUSES to act if the leak is already on the remote (that would need a
REM      force-push, which is FORBIDDEN). It tells you to rotate the key instead.
REM    * Uses `git reset --soft` ONLY. Never --hard, never rebase, never amend,
REM      never filter-branch, never force-push. NO file content is ever lost.
REM    * The recovered commit stays in `git reflog` for ~90 days regardless.
REM
REM  USAGE
REM    uncommit-keys.bat          scan, then ask before fixing
REM    uncommit-keys.bat /y       scan and fix without asking
REM    uncommit-keys.bat /scan    report only, never change anything
REM    uncommit-keys.bat /?       this help
REM
REM  EXIT CODES   0 = clean   1 = leak found (scan mode)   2 = leak already pushed
REM               3 = not a git repo / git missing
REM ============================================================================

cd /d "%~dp0"

set "MODE=fix"
set "ASSUME_YES=0"
for %%A in (%*) do (
    if /i "%%~A"=="/scan"   set "MODE=scan"
    if /i "%%~A"=="/y"      set "ASSUME_YES=1"
    if /i "%%~A"=="/?"      goto :usage
    if /i "%%~A"=="-h"      goto :usage
    if /i "%%~A"=="--help"  goto :usage
)

REM --- the tracked files that legitimately carry real secrets locally ---------

echo(
echo ============================================================
echo   uncommit-keys  -  secret-leak check for %CD%
echo ============================================================

git rev-parse --is-inside-work-tree >nul 2>&1
if errorlevel 1 (
    echo   [X] Not a git repository ^(or git is not on PATH^).
    exit /b 3
)

REM --- resolve the upstream branch we compare against -------------------------
set "UP="
for /f "delims=" %%U in ('git rev-parse --abbrev-ref --symbolic-full-name "@{u}" 2^>nul') do set "UP=%%U"
if not defined UP set "UP=origin/main"

git rev-parse --verify --quiet "%UP%" >nul 2>&1
if errorlevel 1 (
    echo   [X] Cannot resolve upstream '%UP%'. Run: git fetch origin
    exit /b 3
)

set "AHEAD=0"
for /f %%N in ('git rev-list --count %UP%..HEAD 2^>nul') do set "AHEAD=%%N"

echo   upstream        : %UP%
echo   unpushed commits: %AHEAD%
echo(

REM --- safety: data.keys must never be tracked --------------------------------
git ls-files --error-unmatch data.keys >nul 2>&1
if not errorlevel 1 (
    echo   [!!] data.keys is TRACKED by git. It must be gitignored. Fix that first.
    echo(
)

call :scan
if "%PUSHEDLEAK%"=="1" (
    echo(
    echo ============================================================
    echo   STOP  -  a secret is ALREADY on the remote ^(%UP%^).
    echo ============================================================
    echo   This CANNOT be fixed by uncommitting: the commit is published,
    echo   and rewriting/force-pushing published history is FORBIDDEN.
    echo(
    echo   Do this instead:
    echo     1. ROTATE / REVOKE the exposed key at the provider NOW.
    echo     2. python regen_secrets.py --mode push-able
    echo     3. git add ^<the scrubbed files^>
    echo     4. git commit -m "Redact leaked key, by angelahack1"
    echo     5. git push origin main          ^(a NEW forward commit^)
    echo   The past stays untouched. Tell Angela before doing anything else.
    exit /b 2
)

if "%NLEAK%"=="0" if "%NSTAGED%"=="0" (
    echo   [OK] No real keys in your unpushed commits or staged changes.
    echo   [OK] Safe to push.
    exit /b 0
)

echo(
echo   Found %NLEAK% leaked file^(s^) in unpushed commits, %NSTAGED% staged.

if /i "%MODE%"=="scan" (
    echo   ^(scan mode - nothing changed^)
    exit /b 1
)

if "%ASSUME_YES%"=="0" (
    echo(
    echo   Planned fix ^(local only, NOTHING is deleted^):
    if not "%NLEAK%"=="0" echo     git reset --soft %UP%        ^<- undo unpushed commit^(s^), keep every change
    echo     git reset HEAD -- ^<secret files^>   ^<- unstage them back to normal
    if "%AHEAD%"=="1" echo     git commit -m "^<your original message^>"
    echo(
    set /p "ANS=  Proceed? [y/N] "
    if /i not "!ANS!"=="y" (
        echo   Aborted. Nothing changed.
        exit /b 1
    )
)

REM --- save the FULL original commit message (subject + body + trailers) ------
REM     A message FILE + `git commit -F` preserves multi-line messages exactly
REM     and sidesteps every batch quote-escaping trap.
set "MSGFILE=%~dp0Temp\uncommit-keys-msg.txt"
set "HAVEMSG="
if not exist "%~dp0Temp" mkdir "%~dp0Temp" >nul 2>&1
if not "%AHEAD%"=="0" (
    git log -1 --pretty=%%B > "!MSGFILE!" 2>nul
    if exist "!MSGFILE!" set "HAVEMSG=1"
)

echo(
if not "%NLEAK%"=="0" (
    echo   -^> git reset --soft %UP%
    git reset --soft %UP%
    if errorlevel 1 ( echo   [X] reset failed - nothing else attempted. & exit /b 3 )
)

echo   -^> unstaging the secret files
git reset -q HEAD -- %SECRETS%

if "%AHEAD%"=="1" (
    if defined HAVEMSG (
        echo   -^> git commit -F ^(your original message, preserved verbatim^)
        git commit -q -F "!MSGFILE!"
        del "!MSGFILE!" >nul 2>&1
    ) else (
        echo   [!] Could not read the original message. Your safe changes stay STAGED.
        echo       Commit them yourself with: git commit -m "your message"
    )
) else (
    if not "%AHEAD%"=="0" (
        echo   [!] %AHEAD% commits were folded back into the staging area.
        echo       Your safe changes stay STAGED - commit them yourself:
        echo         git commit -m "your message"
    )
)

REM --- prove it worked --------------------------------------------------------
echo(
echo   verifying...
call :scan
if "%NLEAK%"=="0" if "%NSTAGED%"=="0" (
    echo   [OK] Clean. The secret files are back to normal 'modified, not staged'.
    echo   [OK] Your keys are untouched on disk. Safe to push.
    exit /b 0
)
echo   [X] Still dirty - do NOT push. Show this output to Claude/Angela.
exit /b 1


REM ===========================================================================
:scan
REM  Sets NLEAK (leaks in unpushed commits), NSTAGED (leaks staged),
REM       PUSHEDLEAK (1 if the remote itself already holds real keys).
set "NLEAK=0"
set "NSTAGED=0"
set "PUSHEDLEAK=0"

for %%F in (%SECRETS%) do (
    REM placeholders the upstream (correct, push-able) copy has
    set "REF=0"
    for /f %%C in ('git show %UP%:%%F 2^>nul ^| find /c "goes here"') do set "REF=%%C"

    if !REF! EQU 0 (
        git cat-file -e %UP%:%%F 2>nul && (
            echo   [!!] PUSHED LEAK: %%F has 0 placeholders on %UP%
            set "PUSHEDLEAK=1"
        )
    ) else (
        REM ---- is it inside an unpushed commit, and is it dirty? -------------
        set "INDIFF="
        for /f "delims=" %%D in ('git diff --name-only %UP%..HEAD -- %%F 2^>nul') do set "INDIFF=1"
        if defined INDIFF (
            set "CUR=0"
            for /f %%C in ('git show HEAD:%%F 2^>nul ^| find /c "goes here"') do set "CUR=%%C"
            if !CUR! LSS !REF! (
                echo   [LEAK] committed: %%F   ^(placeholders !CUR! ^< !REF! expected^)
                set /a NLEAK+=1
            )
        )
        REM ---- is it staged right now (catches it BEFORE you commit)? --------
        git diff --cached --quiet -- %%F 2>nul || (
            set "SCUR=0"
            for /f %%C in ('git show :%%F 2^>nul ^| find /c "goes here"') do set "SCUR=%%C"
            if !SCUR! LSS !REF! (
                echo   [LEAK] STAGED:    %%F   ^(placeholders !SCUR! ^< !REF! expected^)
                set /a NSTAGED+=1
            )
        )
    )
)
exit /b 0


REM ===========================================================================
:usage
echo(
echo   uncommit-keys.bat  -  undo an UNPUSHED commit that contains real API keys.
echo(
echo     uncommit-keys.bat          scan, then ask before fixing
echo     uncommit-keys.bat /y       scan and fix without asking
echo     uncommit-keys.bat /scan    report only, never change anything
echo     uncommit-keys.bat /?       this help
echo(
echo   Never rewrites pushed history. Never force-pushes. Never loses a file.
exit /b 0