Skip to content

Commit 047aedf

Browse files
committed
fix: custom SAST config normalization + precedence handling
Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
1 parent 5aa26ce commit 047aedf

2 files changed

Lines changed: 92 additions & 7 deletions

File tree

socket_basics/core/config.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,10 @@ def normalize_api_config(api_config: Dict[str, Any]) -> Dict[str, Any]:
897897

898898
# OpenGrep/SAST Configuration
899899
'openGrepNotificationMethod': 'opengrep_notification_method',
900+
'useCustomSastRules': 'use_custom_sast_rules',
901+
'customSastRulePath': 'custom_sast_rule_path',
902+
# Accept common pluralized variant for robustness.
903+
'customSastRulesPath': 'custom_sast_rule_path',
900904

901905
# Socket Tier 1
902906
'socketTier1Enabled': 'socket_tier_1_enabled',
@@ -1004,13 +1008,15 @@ def merge_json_and_env_config(json_config: Dict[str, Any] | None = None) -> Dict
10041008
Returns:
10051009
Merged configuration dictionary
10061010
"""
1011+
logger = logging.getLogger(__name__)
1012+
10071013
# Start with environment defaults (lowest priority)
10081014
config = load_config_from_env()
1015+
logger.info("Configuration sources: environment defaults loaded")
10091016

10101017
# Override with Socket Basics API config if no explicit JSON config provided
10111018
# API config takes precedence over environment defaults
10121019
if not json_config:
1013-
logger = logging.getLogger(__name__)
10141020
logger.debug(" No JSON config provided, attempting to load Socket Basics API config")
10151021
socket_basics_config = load_socket_basics_config()
10161022
logger.debug(f" Socket Basics API config result: {socket_basics_config is not None}")
@@ -1027,7 +1033,10 @@ def merge_json_and_env_config(json_config: Dict[str, Any] | None = None) -> Dict
10271033
continue
10281034
filtered_config[k] = v
10291035
config.update(filtered_config)
1030-
logging.getLogger(__name__).info("Loaded Socket Basics API configuration (overrides environment defaults)")
1036+
if bool(filtered_config.get('socket_has_enterprise', False)):
1037+
logging.getLogger(__name__).info("Loaded Socket Basics API configuration (overrides environment defaults)")
1038+
else:
1039+
logging.getLogger(__name__).info("Loaded Socket plan metadata (free/non-enterprise mode; no dashboard overrides)")
10311040
else:
10321041
logger.debug(" No Socket Basics API config loaded")
10331042

@@ -1049,6 +1058,13 @@ def merge_json_and_env_config(json_config: Dict[str, Any] | None = None) -> Dict
10491058

10501059
# Note: CLI arguments are handled separately and take highest priority
10511060
# They override the config object after this merge completes
1061+
logger.info(
1062+
"Effective custom SAST config: use_custom_sast_rules=%s custom_sast_rule_path=%s all_languages_enabled=%s all_rules_enabled=%s",
1063+
bool(config.get('use_custom_sast_rules', False)),
1064+
config.get('custom_sast_rule_path', ''),
1065+
bool(config.get('all_languages_enabled', False)),
1066+
bool(config.get('all_rules_enabled', False)),
1067+
)
10521068

10531069
return config
10541070

@@ -1087,9 +1103,9 @@ def add_dynamic_cli_args(parser: argparse.ArgumentParser):
10871103
if param_type == 'bool':
10881104
parser.add_argument(option, action='store_true', help=description)
10891105
elif param_type == 'str':
1090-
parser.add_argument(option, type=str, default=default, help=description)
1106+
parser.add_argument(option, type=str, default=None, help=description)
10911107
elif param_type == 'int':
1092-
parser.add_argument(option, type=int, default=default, help=description)
1108+
parser.add_argument(option, type=int, default=None, help=description)
10931109

10941110
except Exception as e:
10951111
logging.getLogger(__name__).warning("Warning: Could not load dynamic CLI args: %s", e)
@@ -1116,9 +1132,9 @@ def add_dynamic_cli_args(parser: argparse.ArgumentParser):
11161132
if p_type == 'bool':
11171133
parser.add_argument(option, action='store_true', help=desc)
11181134
elif p_type == 'int':
1119-
parser.add_argument(option, type=int, default=default, help=desc)
1135+
parser.add_argument(option, type=int, default=None, help=desc)
11201136
else:
1121-
parser.add_argument(option, type=str, default=default, help=desc)
1137+
parser.add_argument(option, type=str, default=None, help=desc)
11221138
except Exception:
11231139
pass
11241140

@@ -1127,7 +1143,7 @@ def parse_cli_args():
11271143
"""Parse command line arguments and return argument parser"""
11281144
parser = argparse.ArgumentParser(description='Socket Security Basics - Dynamic security scanning')
11291145
parser.add_argument('--config', type=str,
1130-
help='Path to JSON configuration file. JSON config is merged with environment variables (environment takes precedence)')
1146+
help='Path to JSON configuration file. JSON config is merged with environment variables (JSON takes precedence)')
11311147
parser.add_argument('--output', type=str, default='.socket.facts.json',
11321148
help='Output file name (default: .socket.facts.json)')
11331149
parser.add_argument('--workspace', type=str, help='Workspace directory to scan')

tests/test_config_custom_sast.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
from socket_basics.core import config as config_module
2+
from socket_basics.core.config import (
3+
create_config_from_args,
4+
merge_json_and_env_config,
5+
normalize_api_config,
6+
parse_cli_args,
7+
)
8+
9+
10+
def test_normalize_api_config_maps_custom_sast_keys():
11+
normalized = normalize_api_config(
12+
{
13+
"useCustomSastRules": True,
14+
"customSastRulePath": ".socket/rules",
15+
}
16+
)
17+
18+
assert normalized["use_custom_sast_rules"] is True
19+
assert normalized["custom_sast_rule_path"] == ".socket/rules"
20+
21+
22+
def test_normalize_api_config_maps_custom_sast_plural_path_alias():
23+
normalized = normalize_api_config({"customSastRulesPath": "custom_rules"})
24+
assert normalized["custom_sast_rule_path"] == "custom_rules"
25+
26+
27+
def test_merge_json_and_env_config_api_overrides_env_custom_sast(monkeypatch):
28+
monkeypatch.setenv("INPUT_USE_CUSTOM_SAST_RULES", "true")
29+
monkeypatch.setenv("INPUT_CUSTOM_SAST_RULE_PATH", ".socket/rules")
30+
31+
monkeypatch.setattr(
32+
config_module,
33+
"load_socket_basics_config",
34+
lambda: {"useCustomSastRules": False, "customSastRulePath": "dashboard/rules"},
35+
)
36+
37+
merged = merge_json_and_env_config()
38+
assert merged["use_custom_sast_rules"] is False
39+
assert merged["custom_sast_rule_path"] == "dashboard/rules"
40+
41+
42+
def test_merge_json_and_env_config_json_overrides_env_custom_sast(monkeypatch):
43+
monkeypatch.setenv("INPUT_USE_CUSTOM_SAST_RULES", "false")
44+
monkeypatch.setenv("INPUT_CUSTOM_SAST_RULE_PATH", "custom_rules")
45+
46+
merged = merge_json_and_env_config(
47+
{"useCustomSastRules": True, "customSastRulePath": ".socket/rules"}
48+
)
49+
assert merged["use_custom_sast_rules"] is True
50+
assert merged["custom_sast_rule_path"] == ".socket/rules"
51+
52+
53+
def test_create_config_from_args_does_not_override_env_custom_path(monkeypatch):
54+
monkeypatch.setenv("INPUT_USE_CUSTOM_SAST_RULES", "true")
55+
monkeypatch.setenv("INPUT_CUSTOM_SAST_RULE_PATH", ".socket/rules")
56+
57+
monkeypatch.setattr(config_module, "_discover_repository", lambda *args, **kwargs: "repo")
58+
monkeypatch.setattr(config_module, "_discover_branch", lambda *args, **kwargs: "branch")
59+
monkeypatch.setattr(config_module, "_discover_commit_hash", lambda *args, **kwargs: "commit")
60+
monkeypatch.setattr(config_module, "_discover_is_default_branch", lambda *args, **kwargs: False)
61+
monkeypatch.setattr(config_module, "_discover_pull_request", lambda *args, **kwargs: 0)
62+
monkeypatch.setattr(config_module, "_discover_committers", lambda *args, **kwargs: [])
63+
64+
parser = parse_cli_args()
65+
args = parser.parse_args([])
66+
config = create_config_from_args(args)
67+
68+
assert config.get("use_custom_sast_rules") is True
69+
assert config.get("custom_sast_rule_path") == ".socket/rules"

0 commit comments

Comments
 (0)