Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ inputs:
required: false
default: ""
socket_additional_params:
description: "Additional CLI params for 'socket scan reach' (comma or space separated). Also reads SOCKET_ADDITIONAL_PARAMS"
description: "Additional CLI params for 'socket scan reach'. Separate options with spaces; repeat list-valued flags. A comma before another option is also supported. Also reads SOCKET_ADDITIONAL_PARAMS."
required: false
default: ""
socket_tier_1_enabled:
Expand Down
26 changes: 25 additions & 1 deletion docs/parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -413,13 +413,37 @@ socket-basics --socket-tier1
```

### `--socket-additional-params SOCKET_ADDITIONAL_PARAMS`
Additional CLI params for 'socket scan reach' (comma or space separated).
Additional CLI params for `socket scan reach`. Separate options with spaces.
For list-valued CLI options, repeat the flag so each value stays attached to
that option. A legacy comma before another option is also accepted. Commas
inside an argument value stay literal, except an unquoted comma followed by a
hyphen is treated as the legacy separator before another option. Quote the
complete value to pass that sequence literally, such as `"value, --text"`.

**Example:**
```bash
socket-basics --socket-tier1 --socket-additional-params "--view=full,--all"
```

To exclude directories from Socket Tier 1 manifest discovery and reachability,
use repeated `--exclude-paths` flags. Paths are relative to the Socket scan
working directory, which defaults to the Basics workspace. `tests` matches only
the `tests` directory at that root; use `**/tests` to match it at any depth. This
option affects the Socket Tier 1 CLI scan. It does not configure other Basics
connectors.

```bash
socket-basics --socket-tier1 --socket-additional-params="--exclude-paths=tests --exclude-paths=fixtures"
```

The same value can be set with `SOCKET_ADDITIONAL_PARAMS` or the GitHub Action's
`socket_additional_params` input:

```yaml
socket_tier_1_enabled: 'true'
socket_additional_params: '--exclude-paths=tests --exclude-paths=fixtures'
```

## Notification Options

### Slack
Expand Down
2 changes: 1 addition & 1 deletion socket_basics/connectors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ connectors:
default: false
- name: socket_additional_params
option: --socket-additional-params
description: "Additional CLI params for 'socket scan reach' (comma or space separated). Also reads SOCKET_ADDITIONAL_PARAMS"
description: "Additional CLI params for 'socket scan reach'. Separate options with spaces; repeat list-valued flags. A comma before another option is also supported. Also reads SOCKET_ADDITIONAL_PARAMS."
env_variable: SOCKET_ADDITIONAL_PARAMS
type: str
default: ""
Expand Down
52 changes: 43 additions & 9 deletions socket_basics/core/connector/socket_tier1/scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,43 @@
logger = logging.getLogger(__name__)


def _split_legacy_parameter_separators(raw: str) -> List[str]:
separated: List[str] = []
quote: Optional[str] = None
escaped: bool = False
index: int = 0

while index < len(raw):
char = raw[index]
if escaped:
separated.append(char)
escaped = False
elif char == "\\" and quote != "'":
separated.append(char)
escaped = True
elif quote:
separated.append(char)
if char == quote:
quote = None
elif char in ("'", '"'):
separated.append(char)
quote = char
elif char == ",":
next_index = index + 1
while next_index < len(raw) and raw[next_index].isspace():
next_index += 1
if next_index < len(raw) and raw[next_index] == "-":
separated.append(" ")
index = next_index - 1
else:
separated.append(char)
else:
separated.append(char)
index += 1

return shlex.split("".join(separated))


class SocketTier1Scanner(BaseConnector):
"""Runs the Socket CLI reachability analysis and returns the generated .socket.facts.json

Expand Down Expand Up @@ -89,15 +126,12 @@ def _parse_additional_params(self) -> List[str]:
)
if not raw:
return []
# Allow comma-separated or regular shell splitting
if ',' in raw:
parts = [p.strip() for p in raw.split(',') if p.strip()]
# further split any parts that contain spaces
out: List[str] = []
for p in parts:
out.extend(shlex.split(p))
return out
return shlex.split(raw)
try:
return _split_legacy_parameter_separators(raw)
except ValueError as error:
raise ConnectorExecutionError(
f"Invalid socket_additional_params: {error}"
) from error

def scan(self) -> Dict[str, Any]:
# Check if Socket Tier 1 reachability scan should be skipped (for Node.js Socket CLI integration).
Expand Down
60 changes: 60 additions & 0 deletions tests/test_socket_tier1_additional_params.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import pytest

from socket_basics.core.connector.base import ConnectorExecutionError
from socket_basics.core.connector.socket_tier1.scanner import SocketTier1Scanner


@pytest.mark.parametrize(
("raw", "expected"),
[
("", []),
(
"--exclude-paths=tests --exclude-paths=fixtures",
["--exclude-paths=tests", "--exclude-paths=fixtures"],
),
(
"--exclude-paths tests --exclude-paths fixtures",
["--exclude-paths", "tests", "--exclude-paths", "fixtures"],
),
(
"--exclude-paths='test data'",
["--exclude-paths=test data"],
),
(
'--exclude-paths="tests,fixtures"',
["--exclude-paths=tests,fixtures"],
),
("--exclude-paths=**/tests", ["--exclude-paths=**/tests"]),
("--view=full,--all", ["--view=full", "--all"]),
(
"--exclude-paths=tests,fixtures --view=full, --all "
'--exclude-paths "test data, -literal"',
[
"--exclude-paths=tests,fixtures",
"--view=full",
"--all",
"--exclude-paths",
"test data, -literal",
],
),
(
'--note="quoted, --option text"',
["--note=quoted, --option text"],
),
(r"--note=left\, --option", ["--note=left,", "--option"]),
],
)
def test_parse_additional_params_preserves_argument_boundaries(raw, expected):
scanner = SocketTier1Scanner({"socket_additional_params": raw})

assert scanner._parse_additional_params() == expected


def test_parse_additional_params_reports_malformed_shell_quotes():
scanner = SocketTier1Scanner({"socket_additional_params": '--exclude-paths "tests'})

with pytest.raises(
ConnectorExecutionError,
match="Invalid socket_additional_params: No closing quotation",
):
scanner._parse_additional_params()
Loading