surshar / claude-code
Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.
Built by Anthropic · github.com/anthropics
The security check looked for defaultMode only in an inline 'settings' input. Also read the file a 'settings' input or a --settings flag in claude_args names, when it is inside the repository, and fail if it sets a permission mode.
| @@ -141,14 +141,41 @@ | ||
| 141 | 141 | f"'claude_args' has '--permission-mode {mode}'. " |
| 142 | 142 | "Change it to '--permission-mode auto'" |
| 143 | 143 | ) |
| 144 | - if "defaultMode" in str(inputs.get("settings", "")): | |
| 145 | - return ( | |
| 146 | - "remove 'defaultMode' from the step's 'settings': " | |
| 147 | - "'settings' must not set a permission mode" | |
| 148 | - ) | |
| 144 | + settings = [("the step's 'settings'", inputs.get("settings", ""))] | |
| 145 | + settings += [ | |
| 146 | + ("'--settings' in 'claude_args'", args[index + 1]) | |
| 147 | + for index, arg in enumerate(args) | |
| 148 | + if arg == "--settings" and index + 1 < len(args) | |
| 149 | + ] | |
| 150 | + settings += [ | |
| 151 | + ("'--settings' in 'claude_args'", arg.split("=", 1)[1]) | |
| 152 | + for arg in args | |
| 153 | + if arg.startswith("--settings=") | |
| 154 | + ] | |
| 155 | + for where, value in settings: | |
| 156 | + if "defaultMode" in settings_text(value): | |
| 157 | + return f"remove 'defaultMode' from {where}: settings must not set a permission mode" | |
| 149 | 158 | return None |
| 150 | 159 | |
| 151 | 160 | |
| 161 | +def settings_text(value) -> str: | |
| 162 | + """The settings JSON a 'settings' value stands for: the value itself, or the contents of | |
| 163 | + the file it names when it is a path inside the repository.""" | |
| 164 | + text = str(value or "").strip() | |
| 165 | + if not text or text.startswith("{"): | |
| 166 | + return text | |
| 167 | + path = pathlib.Path(text) | |
| 168 | + root = pathlib.Path.cwd().resolve() | |
| 169 | + try: | |
| 170 | + resolved = path.resolve() | |
| 171 | + resolved.relative_to(root) | |
| 172 | + except (OSError, ValueError): | |
| 173 | + return text | |
| 174 | + if resolved.is_file(): | |
| 175 | + return resolved.read_text(encoding="utf-8", errors="replace") | |
| 176 | + return text | |
| 177 | + | |
| 178 | + | |
| 152 | 179 | def check_job(file_name: str, job_id: str, job: dict) -> list[str]: |
| 153 | 180 | key = f"{file_name}:{job_id}" |
| 154 | 181 | where = f".github/workflows/{file_name}: job '{job_id}'" |