T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/publish.py:578
- Finding
- Excessive Authentication Cookie Collection and Insecure Plaintext Storage<![CDATA[ ## Vulnerability Details **File Location**: `scripts/publish.py:578-610` **Vulnerability Type**: Excessive credential collection and plaintext credential storage **Risk Level**: High ### Vulnerable Code ```python def cookie_header(cookies: list[dict], want: list[str]) -> tuple[str, list[str]]: pairs = [f"{c['name']}={c['value']}" for c in cookies if c.get("name") and c.get("value")] names = {c["name"] for c in cookies} return "; ".join(pairs), [w for w in want if w not in names] def save_env(cookie_header_str: str) -> None: ENV_FILE.write_text(f"JUEJIN_COOKIE={cookie_header_str}\n", encoding="utf-8") ``` The collected cookies are subsequently persisted during login: ```python cs = tab.cookies(["https://juejin.cn", "https://api.juejin.cn"]) sid = next((c for c in cs if c["name"] == "sessionid"), None) if sid: header, _ = cookie_header(cs, ["sessionid"]) save_env(header) ``` ### Technical Analysis The publishing functionality legitimately requires an authenticated Juejin session, and sending an authentication cookie to `api.juejin.cn` is consistent with the declared functionality. However, the implementation exceeds the minimum required credential scope. Although the login routine checks specifically for `sessionid`, `cookie_header()` serializes every nonempty cookie returned for the Juejin domains. The complete cookie header is then written to `.juejin.env` as plaintext using default filesystem permissions. This creates two separate security issues: 1. **Excessive collection:** Cookies unrelated to the required authenticated API session are retained unnecessarily. 2. **Insecure storage:** Authentication material is stored without owner-only permission enforcement, encryption, secure credential storage, or atomic creation. The repository snapshot also does not contain a `.gitignore`, despite `juejin.env.example` stating that `.juejin.env` is excluded from version control. This increases the risk of accidental credenti ...[truncated 1371 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Persist only an explicit allowlist of cookies required by the API: ```python REQUIRED_COOKIES = {"sessionid"} def cookie_header(cookies: list[dict]) -> str: return "; ".join( f"{c['name']}={c['value']}" for c in cookies if c.get("name") in REQUIRED_COOKIES and c.get("value") ) ``` 2. Create the credential file with owner-only permissions, such as mode `0600` on POSIX systems. 3. Write credentials atomically through a securely created temporary file and then replace the destination. 4. Prefer operating-system credential storage, such as Windows Credential Manager, macOS Keychain, or a Linux Secret Service provider. 5. Add a project `.gitignore` containing at least: ```gitignore .juejin.env .cdp-profile/ _wf/ ``` 6. Clearly document the exact cookies collected, their storage location, retention period, and revocation procedure. 7. Advise users to revoke or rotate the Juejin session immediately if `.juejin.env` may have been exposed. ]]>
