{"record":{"id":"e40801cc71a7382f","repo":"affaan-m/ECC","slug":"stable-source-probing-requires-o-nofollow","errorCode":null,"errorMessage":"stable source probing requires O_NOFOLLOW","messagePattern":"stable source probing requires O_NOFOLLOW","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/workflow.py","lineNumber":62,"sourceCode":"\n\ndef _hash_descriptor(descriptor: int) -> tuple[int, str]:\n    os.lseek(descriptor, 0, os.SEEK_SET)\n    digest = hashlib.sha256()\n    total = 0\n    while True:\n        chunk = os.read(descriptor, 1024 * 1024)\n        if not chunk:\n            break\n        total += len(chunk)\n        digest.update(chunk)\n    return total, digest.hexdigest()\n\n\ndef _stable_probe(path: Path, probe: Probe) -> tuple[dict[str, Any], int, str]:\n    \"\"\"Probe a private snapshot while binding the digest to one stable source object.\"\"\"\n    if not hasattr(os, \"O_NOFOLLOW\"):\n        raise ValueError(\"stable source probing requires O_NOFOLLOW\")\n    descriptor = os.open(path, os.O_RDONLY | os.O_NOFOLLOW)\n    try:\n        before = os.fstat(descriptor)\n        if not stat.S_ISREG(before.st_mode):\n            raise ValueError(\"reference source must be a regular file\")\n        with tempfile.TemporaryDirectory(prefix=\"tasteforge-source-\") as temporary:\n            snapshot = Path(temporary) / f\"source{path.suffix}\"\n            snapshot_fd = os.open(\n                snapshot, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600\n            )\n            try:\n                os.lseek(descriptor, 0, os.SEEK_SET)\n                digest = hashlib.sha256()\n                total = 0\n                while True:\n                    chunk = os.read(descriptor, 1024 * 1024)\n                    if not chunk:\n                        break","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/workflow.py#L44-L80","documentation":"This error is raised by _stable_probe when the running Python interpreter's os module does not expose O_NOFOLLOW, a flag only available on POSIX systems (Linux, macOS, BSDs). O_NOFOLLOW is essential to this workflow because probing a 'stable source' requires opening the file without following symlinks, so the digest is bound to one physical source object. Without the flag the function cannot make that security guarantee, so it refuses to run rather than silently probing an unsafe path. Windows and very old/limited Python builds lack os.O_NOFOLLOW.","triggerScenarios":"Calling _stable_probe (directly or via run_workflow) on a platform whose os module lacks O_NOFOLLOW — typically Windows (no O_NOFOLLOW in os) or a stripped/embedded POSIX Python build.","commonSituations":"Running the tasteforge workflow on Windows or WSL1 configurations, in a CI container with a minimal/odd Python runtime, or after a port that replaced os with a shim lacking O_NOFOLLOW.","solutions":["Run the workflow on a POSIX platform (Linux/macOS/BSD) where os.O_NOFOLLOW exists.","Verify with `python -c \"import os; print(hasattr(os, 'O_NOFOLLOW'))\"` before running; if False, switch interpreters or platforms.","If Windows support is required, resolve `path.resolve(strict=True)` and verify it is not a symlink before reading, accepting the weaker guarantee instead of O_NOFOLLOW."],"exampleFix":"// before (Windows: os has no O_NOFOLLOW)\npython workflow.py probe source.py\n\n// after (run on Linux/macOS or check capability first)\nimport os\nassert hasattr(os, \"O_NOFOLLOW\"), \"run on a POSIX platform\"\npython workflow.py probe source.py","handlingStrategy":"validation","validationCode":"import os\nif not hasattr(os, \"O_NOFOLLOW\"):\n    raise RuntimeError(\"tasteforge stable probing requires a POSIX platform with O_NOFOLLOW\")","typeGuard":"def supports_o_nofollow() -> bool:\n    import os\n    return hasattr(os, \"O_NOFOLLOW\")","tryCatchPattern":null,"preventionTips":["Run the tool on Linux/macOS/BSD only; document Windows as unsupported.","Add a startup capability check before invoking the workflow.","Pin CI runners to POSIX images."],"tags":["filesystem","platform-compatibility","security"],"backgroundTag":"unsupported-platform","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}