critical Threat analysis

Sicoob.Sdk NuGet Certificate Exfiltration

Malicious Sicoob.Sdk NuGet releases impersonated a banking SDK and exfiltrated Sicoob client IDs, PFX passwords, and base64-encoded PFX certificate archives through a hardcoded Sentry endpoint.

#nuget#dotnet#package-impersonation#certificate-theft#credential-theft#financial-services
On this page 0% read

    Executive Summary

    Socket published research on May 28, 2026 showing that NuGet package Sicoob.Sdk versions 2.0.0 through 2.0.4 impersonated an official Sicoob .NET SDK and exfiltrated banking API authentication material through Sentry telemetry [1]. Halting Problems downloaded the available NuGet artifacts and confirmed that the affected DLLs contain the hardcoded Sentry destination plus static selectors for SentrySdk, CaptureMessage, ReadAllBytes, ToBase64String, cliend_id:, and pass: in lib/net8.0/Sicoob.Sdk.dll [2], [3]. The package’s public source repository presents ordinary SDK behavior for loading a PFX certificate into an mTLS HTTP client, but the inspected SicoobClient.cs source does not contain the Sentry initialization or capture path observed in the distributed NuGet DLL [6].

    This should be treated as a malicious package impersonation event, not a benign telemetry mistake. Any organization that installed or executed [email protected] through 2.0.4 with real Sicoob credentials should assume the supplied client ID, PFX archive contents, and PFX password were exposed unless local network and endpoint telemetry proves otherwise [1].

    Key Facts

    threat_type: "NuGet package impersonation and credential exfiltration"
    ecosystem: "NuGet, .NET"
    registry: "NuGet"
    affected_packages:
      - "Sicoob.Sdk"
    malicious_versions:
      - "2.0.0"
      - "2.0.1"
      - "2.0.2"
      - "2.0.3"
      - "2.0.4"
    known_non_malicious_versions:
      - "1.0.0"
    related_nuget_owner: "sicoob"
    related_github_org: "Sicoob-Cooperativa"
    exfiltration_endpoint_defanged: "hxxps://d565e3f03d0b1a7c8935d7ff94237316@o4511335034847232[.]ingest[.]de[.]sentry[.]io/4511337546317904"
    credentials_at_risk:
      - "Sicoob API client IDs"
      - "PFX certificate archives"
      - "PFX passwords"
      - "Sicoob access tokens derived from exposed client credentials"
      - "raw boleto API response data"
    confidence: "high"
    attribution: "unknown"

    Source Confidence and Claim Ledger

    ClaimStatusEvidence
    Sicoob.Sdk versions 2.0.0 through 2.0.4 exfiltrate client IDs, PFX passwords, and base64-encoded PFX contents through Sentry telemetry.confirmedSocket static and dynamic analysis, plus local artifact string verification for the affected NuGet packages [1], [2], [3].
    The NuGet package set currently includes 1.0.0, 2.0.0, 2.0.1, 2.0.2, 2.0.3, and 2.0.4.confirmedNuGet flat-container index and registration metadata [2], [3].
    The public GitHub repository is a source-to-package mismatch for the malicious behavior.confirmedThe public SicoobClient.cs loads PFX material into X509Certificate2, while local package inspection and Socket’s IL excerpt show Sentry capture behavior in the DLL [1], [6].
    Sicoob-Cooperativa should not be treated as an authorized Sicoob source without direct Sicoob confirmation.likelyThe GitHub org was created on 2026-05-04, is unverified, has zero followers, and differs from the older github[.]com/Sicoob account created in 2017 [4], [5].
    Downstream financial API abuse, confirmed victims, or actor identity are known.not_observedNo primary evidence in this collection names victims, successful fraud, or a threat actor.

    What Happened

    The malicious package used the trust position of a banking SDK. Socket reported that Sicoob.Sdk advertised itself as an official C# SDK for Sicoob API integrations and accepted a client ID, PFX file path, and PFX password as normal constructor inputs [1]. That is a plausible shape for an mTLS-based financial API client: a PFX archive can contain the client certificate and private key needed to authenticate the integration.

    The abuse is in what happened next. Socket found that production-mode SicoobClient construction initialized Sentry, read the supplied PFX file from disk, base64-encoded it, and captured a Sentry message containing the client ID, plaintext PFX password, and encoded certificate material [1]. Our local package inspection confirmed that 2.0.0 through 2.0.4 carry the Sentry destination and the static string set needed to support that behavior in lib/net8.0/Sicoob.Sdk.dll [2], [3].

    NuGet metadata and package contents also support the impersonation assessment. The package uses Sicoob branding, depends on many Sicoob-Cooperativa.Sicoob.* modules, and includes a Sentry dependency in the .nuspec files [3]. The linked GitHub organization Sicoob-Cooperativa was created on 2026-05-04, is not GitHub-verified, exposes no public members through the API, and has zero followers [4]. That posture is materially different from the older github[.]com/Sicoob account, created in 2017 and presenting itself as “Confederacao Nacional das Cooperativas do Sicoob” with a www.sicoob.com.br link [5].

    Artifact and Provenance Notes

    Halting Problems downloaded the available Sicoob.Sdk package artifacts from NuGet’s flat-container API on May 28, 2026. The package index still listed all six observed versions at collection time [2]. The SHA-256 values of the downloaded .nupkg files were:

    artifact_hashes_sha256:
      [email protected]: "87b66028e491573b787ee00bc81916241047e035d152dfbf4807b57c1bbbb043"
      [email protected]: "7d2332e76c266509cdec8b552ccc839f50c28e6b01070071257bd3f57d1d9da2"
      [email protected]: "f0dff53969080584560b2971411415bdf9064d5a5a50185c4ae018943e7d5cbe"
      [email protected]: "94eb8da6703dd073184015c9e3cb34e9b6153fc499c9cb1a7db6e4361ec349dd"
      [email protected]: "ac9dc55f13d973e05865e9674c8b8e6744e7fbfca3355199b292f614f13ac7bc"
      [email protected]: "190dbcafa776e8cc221106414b8fbd68252d98438c5e46b8449788fbe70316a4"

    The extracted .nuspec files include repository commit values, but not a repository URL. The public GitHub repository does have a SicoobClient.cs file that handles clientId, pfxPath, and pfxPassword for mTLS, but the inspected source lacks SentrySdk.Init, SentrySdk.CaptureMessage, the Sentry ingestion host, and a direct source-level PFX file exfiltration path [6]. That mismatch is a key reason this incident is classified as supply-chain abuse instead of a normal SDK defect.

    Impact Determination

    ClassificationCriteriaRequired actionClosure condition
    Confirmed compromise[email protected] through 2.0.4 executed and endpoint, proxy, EDR, or Sentry-ingest telemetry shows outbound activity to the listed Sentry host.Isolate the executing host or runner, preserve package and network evidence, revoke Sicoob client IDs where possible, revoke and replace PFX certificates, and rotate PFX passwords from a clean system.Replaced certificates and client IDs are in use, old material is rejected by Sicoob-side controls, and no suspicious token issuance or API activity remains unresolved.
    Presumed exposedAffected package version was installed, restored, built, imported, or used by an app or CI job that had real Sicoob PFX material, but telemetry cannot prove network exfiltration.Treat the PFX archive, password, client ID, and any derived tokens as exposed. Rebuild from clean dependencies and audit financial API activity.Every credential reachable from the affected runtime has been rotated or explicitly accepted by the risk owner.
    Potentially exposedSicoob.Sdk appears in manifests, caches, lockfiles, packages, or code, but execution with real credentials is not established.Collect package restore logs, application startup logs, endpoint telemetry, and secret-store access logs for the relevant period.Each hit is dispositioned as confirmed compromise, presumed exposed, or not exposed.
    Not exposedNo affected versions or indicators appear in source, lockfiles, package caches, build artifacts, endpoints, CI logs, proxy logs, or deployed services.Preserve negative search output and block future use of the package identity.Coverage includes developer endpoints, CI runners, production hosts, and NuGet caches.
    UnknownPackage inventory, endpoint telemetry, network logs, Sicoob logs, or CI logs are unavailable.Keep the asset in scope and prefer credential rotation for production banking credentials.Missing evidence is recovered or the residual risk is formally accepted.

    Downstream Abuse Audits

    Script: GitHub organization run, release, secret, and workflow audit

    #!/usr/bin/env python3
    import os
    import sys
    import json
    import subprocess
    from pathlib import Path
    
    if "ORG" not in os.environ:
        print("ERROR: Set ORG environment variable to the GitHub organization to audit", file=sys.stderr)
        sys.exit(1)
    
    ORG = os.environ["ORG"]
    SINCE = "2026-05-28T00:00:00Z"
    UNTIL = "2026-05-28T23:59:59Z"
    OUT = Path(os.environ.get("OUT", "hp-sicoob-sdk-nuget-certificate-exfiltration-github-audit"))
    
    SELECTORS = [
      "Sicoob.Sdk",
      "2.0.0",
      "2.0.1",
      "2.0.2",
      "2.0.3",
      "2.0.4",
      "lib/net8.0/Sicoob.Sdk.dll",
      "o4511335034847232.ingest.de.sentry.io",
      "Sicoob.Sdk.dll",
      "https://d565e3f03d0b1a7c8935d7ff94237316@o4511335034847232.ingest.de.sentry.io/4511337546317904",
      "7d2332e76c266509cdec8b552ccc839f50c28e6b01070071257bd3f57d1d9da2",
      "f0dff53969080584560b2971411415bdf9064d5a5a50185c4ae018943e7d5cbe",
      "94eb8da6703dd073184015c9e3cb34e9b6153fc499c9cb1a7db6e4361ec349dd",
      "ac9dc55f13d973e05865e9674c8b8e6744e7fbfca3355199b292f614f13ac7bc",
      "190dbcafa776e8cc221106414b8fbd68252d98438c5e46b8449788fbe70316a4",
      "d565e3f03d0b1a7c8935d7ff94237316",
    ]
    
    # Positive signal: a workflow run, release, secret, key, package, or workflow change overlaps the exposure window and references an incident selector.
    # Remediation trigger: unauthorized post-exposure write activity or a secret-bearing run matching an incident selector requires token revocation and downstream cloud/registry review.
    
    OUT.mkdir(parents=True, exist_ok=True)
    (OUT / "runs").mkdir(exist_ok=True)
    (OUT / "logs").mkdir(exist_ok=True)
    (OUT / "repos").mkdir(exist_ok=True)
    
    # 1. Write incident-selectors file
    selectors_file = OUT / "incident-selectors.txt"
    with open(selectors_file, "w") as sf:
        for s in SELECTORS:
            if s:
                sf.write(s + "\n")
    
    # 2. Get list of repos
    print(f"[+] Fetching repositories for organization: {ORG}")
    repo_res = subprocess.run(["gh", "repo", "list", ORG, "--limit", "1000", "--json", "nameWithOwner"], capture_output=True, text=True)
    if repo_res.returncode != 0:
        print(f"[-] Failed to fetch repos: {repo_res.stderr}", file=sys.stderr)
        sys.exit(1)
    
    repos = [r["nameWithOwner"] for r in json.loads(repo_res.stdout)]
    
    for repo in repos:
        safe_repo = repo.replace("/", "__")
        print(f"[+] Auditing repository: {repo}")
    
        # Check runs in the window
        runs_res = subprocess.run([
            "gh", "api", f"/repos/{repo}/actions/runs",
            "-f", "per_page=100",
            "-f", f"created=>={SINCE}",
            "--paginate"
        ], capture_output=True, text=True)
    
        if runs_res.returncode == 0:
            try:
                all_runs = json.loads(runs_res.stdout).get("workflow_runs", [])
                filtered_runs = [r for r in all_runs if r["created_at"] <= UNTIL]
    
                if filtered_runs:
                    with open(OUT / "runs" / f"{safe_repo}-runs.jsonl", "w") as rf:
                        for run in filtered_runs:
                            rf.write(json.dumps(run) + "\n")
    
                            # Fetch log dynamically
                            run_id = str(run["id"])
                            log_res = subprocess.run(["gh", "run", "view", run_id, "--repo", repo, "--log"], capture_output=True, text=True)
                            if log_res.returncode == 0:
                                (OUT / "logs" / f"{safe_repo}-{run_id}.log").write_text(log_res.stdout)
    
                            # Fetch details
                            view_res = subprocess.run(["gh", "run", "view", run_id, "--repo", repo, "--json", "databaseId,workflowName,headSha,event,createdAt,jobs"], capture_output=True, text=True)
                            if view_res.returncode == 0:
                                (OUT / "runs" / f"{safe_repo}-{run_id}.json").write_text(view_res.stdout)
            except Exception as e:
                print(f"[-] Error parsing runs for {repo}: {e}")
    
        # Check releases in window
        subprocess.run(["gh", "api", f"/repos/{repo}/releases", "-f", "per_page=100", "--paginate"], capture_output=True)
        # Check repo secrets updated in window
        subprocess.run(["gh", "api", f"/repos/{repo}/actions/secrets", "-f", "per_page=100", "--paginate"], capture_output=True)
        # Check deploy keys
        subprocess.run(["gh", "api", f"/repos/{repo}/keys", "-f", "per_page=100", "--paginate"], capture_output=True)
    
    # Scan output directory for any indicator selector matches
    print("[+] Scanning gathered telemetry for indicator matches...")
    subprocess.run(["rg", "-n", "--hidden", "--fixed-strings", "-f", str(selectors_file), str(OUT)], capture_output=False)
    
    print(f"[+] Wrote GitHub audit artifacts under {OUT}")

    Script: cloud OIDC and deployment credential follow-on audit

    #!/usr/bin/env python3
    import os
    import json
    import subprocess
    from pathlib import Path
    
    SINCE = "2026-05-28T00:00:00Z"
    UNTIL = "2026-05-28T23:59:59Z"
    OUT = Path(os.environ.get("OUT", "hp-sicoob-sdk-nuget-certificate-exfiltration-cloud-audit"))
    AWS_REGIONS = os.environ.get("AWS_REGIONS", "us-east-1").split(",")
    
    # Positive signal: token exchange or privileged write activity occurs in the exposure window from GitHub, CI/CD, package registry, or deployment automation identity.
    # Remediation trigger: unexpected write, deploy, IAM, secret, or registry activity tied to an exposed CI/CD path requires trust-policy disablement and credential rotation.
    
    OUT.mkdir(parents=True, exist_ok=True)
    
    # 1. AWS CloudTrail Audit
    print("[+] Querying AWS CloudTrail for Web Identity token exchanges...")
    aws_events = []
    for region in AWS_REGIONS:
        res = subprocess.run([
            "aws", "cloudtrail", "lookup-events",
            "--region", region,
            "--start-time", SINCE,
            "--end-time", UNTIL,
            "--lookup-attributes", "AttributeKey=EventName,AttributeValue=AssumeRoleWithWebIdentity",
            "--output", "json"
        ], capture_output=True, text=True)
    
        if res.returncode == 0:
            try:
                events = json.loads(res.stdout).get("Events", [])
                for event in events:
                    ct = json.loads(event.get("CloudTrailEvent", "{}"))
                    ct["region"] = region
                    aws_events.append(ct)
            except Exception as e:
                print(f"[-] Error parsing AWS CloudTrail events: {e}")
    
    if aws_events:
        with open(OUT / "aws-assume-role-with-web-identity.jsonl", "w") as f:
            for ev in aws_events:
                f.write(json.dumps(ev) + "\n")
    
        # Audit follow-on events for returned access keys
        for ev in aws_events:
            access_key = ev.get("responseElements", {}).get("credentials", {}).get("accessKeyId")
            region = ev.get("region", "us-east-1")
            if access_key:
                print(f"[+] Enumerating AWS events for AccessKey: {access_key}")
                f_res = subprocess.run([
                    "aws", "cloudtrail", "lookup-events",
                    "--region", region,
                    "--start-time", SINCE,
                    "--end-time", UNTIL,
                    "--lookup-attributes", f"AttributeKey=AccessKeyId,AttributeValue={access_key}",
                    "--output", "json"
                ], capture_output=True, text=True)
                if f_res.returncode == 0:
                    try:
                        f_events = json.loads(f_res.stdout).get("Events", [])
                        with open(OUT / "aws-follow-on-api-calls.jsonl", "a") as ff:
                            for fe in f_events:
                                ff.write(fe.get("CloudTrailEvent", "{}") + "\n")
                    except Exception as e:
                        print(f"[-] Error writing follow-on events: {e}")
    
    # 2. Azure Activity Log Audit
    print("[+] Querying Azure activity logs...")
    az_res = subprocess.run([
        "az", "monitor", "activity-log", "list",
        "--start-time", SINCE,
        "--end-time", UNTIL,
        "--query", "[?contains(operationName.value, 'write') || contains(operationName.value, 'delete') || contains(operationName.value, 'Microsoft.ManagedIdentity')]",
        "-o", "json"
    ], capture_output=True, text=True)
    
    if az_res.returncode == 0:
        (OUT / "azure-write-delete-activity.json").write_text(az_res.stdout)
    
    # 3. GCP Logging Audit
    print("[+] Querying GCP Cloud Logging...")
    gcp_filter = f'timestamp>="{SINCE}" AND timestamp<="{UNTIL}" AND (protoPayload.methodName="google.sts.v1.SecurityTokenService.ExchangeToken" OR protoPayload.methodName:"GenerateAccessToken" OR protoPayload.methodName:"CreateServiceAccountKey" OR protoPayload.methodName:"SetIamPolicy")'
    gcp_res = subprocess.run([
        "gcloud", "logging", "read", gcp_filter,
        "--format", "json"
    ], capture_output=True, text=True)
    
    if gcp_res.returncode == 0:
        (OUT / "gcp-token-and-iam-activity.json").write_text(gcp_res.stdout)
    
    print(f"[+] Wrote cloud audit artifacts under {OUT}")

    Script: registry metadata and artifact audit

    #!/usr/bin/env python3
    import os
    import json
    import subprocess
    from pathlib import Path
    
    SINCE = "2026-05-28T00:00:00Z"
    OUT = Path(os.environ.get("OUT", "hp-sicoob-sdk-nuget-certificate-exfiltration-registry-audit"))
    PACKAGES = [
      "Sicoob.Sdk",
    ]
    VERSIONS = [
      "2.0.0",
      "2.0.1",
      "2.0.2",
      "2.0.3",
      "2.0.4",
    ]
    
    # Positive signal: workflow files or extensions reference the affected action/extension names or versions.
    # Remediation trigger: exposed secrets or OIDC federation policies must be immediately rotated.
    
    OUT.mkdir(parents=True, exist_ok=True)
    
    with open(OUT / "affected-versions.txt", "w") as av:
        for version in VERSIONS:
            if version:
                av.write(version + "\n")
    
        # 1. Search local workspace files for the affected actions/extensions
        print("[+] Scanning workspace workflows for selectors...")
        for file in Path(".").glob(".github/workflows/**/*.yml"):
            subprocess.run(["rg", "-n", "--hidden", "--fixed-strings", "-f", str(OUT / "affected-versions.txt"), str(file)])
    
        # 2. HOW TO ROTATE EXPOSED GITHUB ACTIONS SECRETS:
        # Overwrite compromised secrets with newly generated credentials:
        # subprocess.run(["gh", "secret", "set", "COMPROMISED_SECRET_NAME", "--body", "my-new-secret-value", "--repo", "my-org/my-repo"])
        # For organization-level secrets:
        # subprocess.run(["gh", "secret", "set", "COMPROMISED_SECRET_NAME", "--org", "my-org", "--visibility", "private"])
        # Revoke compromised OIDC federated trust credentials in AWS/GCP and redeploy the IAM trust policy:
        # subprocess.run(["aws", "iam", "update-assume-role-policy", "--role-name", "my-role-name", "--policy-document", "file://new-clean-trust-policy.json"])
    
    print(f"[+] Wrote registry audit artifacts under {OUT}")

    Indicators of Compromise

    packages:
      - "[email protected]"
      - "[email protected]"
      - "[email protected]"
      - "[email protected]"
      - "[email protected]"
    domains:
      - "o4511335034847232[.]ingest[.]de[.]sentry[.]io"
    urls:
      - "hxxps://d565e3f03d0b1a7c8935d7ff94237316@o4511335034847232[.]ingest[.]de[.]sentry[.]io/4511337546317904"
    files:
      - "lib/net8.0/Sicoob.Sdk.dll"
    hashes:
      - "7d2332e76c266509cdec8b552ccc839f50c28e6b01070071257bd3f57d1d9da2"
      - "f0dff53969080584560b2971411415bdf9064d5a5a50185c4ae018943e7d5cbe"
      - "94eb8da6703dd073184015c9e3cb34e9b6153fc499c9cb1a7db6e4361ec349dd"
      - "ac9dc55f13d973e05865e9674c8b8e6744e7fbfca3355199b292f614f13ac7bc"
      - "190dbcafa776e8cc221106414b8fbd68252d98438c5e46b8449788fbe70316a4"
    telemetry_selectors:
      - "PackageReference Include=\"Sicoob.Sdk\""
      - "dotnet add package Sicoob.Sdk"
      - "new SicoobClient("
      - "cliend_id:"
      - "pass:"
      - "Boleto:"
      - "SentrySdk"
      - "CaptureMessage"
      - "ReadAllBytes"
      - "ToBase64String"

    Detection and Hunting

    Script: local repository and exported telemetry scope

    #!/usr/bin/env python3
    import os
    import sys
    import json
    import subprocess
    from pathlib import Path
    
    ROOT = sys.argv[1] if len(sys.argv) > 1 else "."
    LOG_ROOT = os.environ.get("LOG_ROOT", "")
    OUT = Path(os.environ.get("OUT", "hp-sicoob-sdk-nuget-certificate-exfiltration-scope"))
    SINCE = "2026-05-28T00:00:00Z"
    UNTIL = "2026-05-28T23:59:59Z"
    
    PACKAGES = [
      "Sicoob.Sdk",
    ]
    VERSIONS = [
      "2.0.0",
      "2.0.1",
      "2.0.2",
      "2.0.3",
      "2.0.4",
    ]
    FILES = [
      "lib/net8.0/Sicoob.Sdk.dll",
    ]
    DOMAINS = [
      "o4511335034847232.ingest.de.sentry.io",
      "Sicoob.Sdk.dll",
    ]
    URLS = [
      "https://d565e3f03d0b1a7c8935d7ff94237316@o4511335034847232.ingest.de.sentry.io/4511337546317904",
    ]
    IPS = [
    ]
    HASHES = [
      "7d2332e76c266509cdec8b552ccc839f50c28e6b01070071257bd3f57d1d9da2",
      "f0dff53969080584560b2971411415bdf9064d5a5a50185c4ae018943e7d5cbe",
      "94eb8da6703dd073184015c9e3cb34e9b6153fc499c9cb1a7db6e4361ec349dd",
      "ac9dc55f13d973e05865e9674c8b8e6744e7fbfca3355199b292f614f13ac7bc",
      "190dbcafa776e8cc221106414b8fbd68252d98438c5e46b8449788fbe70316a4",
      "d565e3f03d0b1a7c8935d7ff94237316",
    ]
    PROCESS_PATTERNS = [
    ]
    NETWORK_PATTERNS = [
    ]
    
    # Positive signal: repository, lockfile, artifact, process, or network telemetry contains one of the exact incident selectors above.
    # Escalation: any match tied to a production build, CI run, deployed asset, or secret-bearing host moves the asset to presumed exposed.
    
    OUT.mkdir(parents=True, exist_ok=True)
    indicators_file = OUT / "indicators.txt"
    
    # Collect unique indicators
    indicators = set()
    for group in [PACKAGES, VERSIONS, FILES, DOMAINS, URLS, IPS, HASHES, PROCESS_PATTERNS, NETWORK_PATTERNS]:
        for val in group:
            if val:
                indicators.add(val)
    
    with open(indicators_file, "w") as f:
        for ind in sorted(indicators):
            f.write(ind + "\n")
    
    print(f"[+] Written unique selectors to {indicators_file}")
    
    # Walk local directory
    print(f"[+] Scanning directory: {ROOT} for selectors...")
    matches = []
    exclude_dirs = {"node_modules", "vendor", "dist", ".git"}
    for root, dirs, filenames in os.walk(ROOT):
        dirs[:] = [d for d in dirs if d not in exclude_dirs]
        for filename in filenames:
            filepath = Path(root) / filename
            try:
                content = filepath.read_text(errors="ignore")
                for ind in indicators:
                    if ind in content:
                        matches.append(f"{filepath}: found '{ind}'")
            except Exception:
                pass
    
    if matches:
        (OUT / "repository-indicator-matches.txt").write_text("\n".join(matches) + "\n")
        print(f"[!] Found {len(matches)} matches in codebase!")
    
    # Optional Log Scanning
    if LOG_ROOT and os.path.exists(LOG_ROOT):
        print(f"[+] Scanning telemetry log directory: {LOG_ROOT}...")
        log_matches = []
        for root, _, filenames in os.walk(LOG_ROOT):
            for filename in filenames:
                filepath = Path(root) / filename
                try:
                    content = filepath.read_text(errors="ignore")
                    for ind in indicators:
                        if ind in content:
                            log_matches.append(f"{filepath}: found '{ind}'")
                except Exception:
                    pass
        if log_matches:
            (OUT / "exported-telemetry-indicator-matches.txt").write_text("\n".join(log_matches) + "\n")
            print(f"[!] Found {len(log_matches)} matches in logs!")
    
        if PACKAGES:
            registry_dir = OUT / "registry"
            registry_dir.mkdir(exist_ok=True)
    
    print(f"[+] Wrote scope artifacts under {OUT}")

    Remediation

    Containment: block Sicoob.Sdk in NuGet package policy, remove the package from source and lockfiles, isolate hosts or runners that executed affected versions with real credentials, and preserve the affected .nupkg, build logs, process telemetry, and network logs.

    Eradication: replace the dependency only through a Sicoob-controlled and independently verified source path. Delete affected NuGet caches on developer workstations, CI runners, build images, and deployment hosts. Rebuild release artifacts from clean dependency state.

    Credential recovery: revoke and replace any PFX certificates supplied to affected versions, rotate PFX passwords, rotate or disable exposed client IDs where Sicoob controls allow it, invalidate derived access tokens, and review Sicoob API audit logs for suspicious token issuance or financial operations.

    Closure gates: all affected versions are absent from source, lockfiles, caches, images, and deployments; old certificates and passwords no longer authenticate; Sicoob API logs have been reviewed for the exposure window; and package allowlist controls prevent accidental reintroduction.

    Sources

    1. Socket: Malicious NuGet Package Impersonates Sicoob SDK to Exfiltrate Banking Certificates and Passwords
    2. NuGet flat-container index for Sicoob.Sdk
    3. NuGet registration index for Sicoob.Sdk
    4. GitHub API: Sicoob-Cooperativa organization
    5. GitHub API: Sicoob account
    6. Sicoob-Cooperativa public SicoobClient.cs source

    IOC Clipboard

    10 IOCs
    Defang IOCs
    domain o4511335034847232.ingest.de.sentry.io o4511335034847232[.]ingest[.]de[.]sentry[.]io
    domain Sicoob.Sdk.dll Sicoob[.]Sdk[.]dll
    url https://d565e3f03d0b1a7c8935d7ff94237316@o4511335034847232.ingest.de.sentry.io/4511337546317904 hxxps://d565e3f03d0b1a7c8935d7ff94237316@o4511335034847232[.]ingest[.]de[.]sentry[.]io/4511337546317904
    hash 7d2332e76c266509cdec8b552ccc839f50c28e6b01070071257bd3f57d1d9da2 7d2332e76c266509cdec8b552ccc839f50c28e6b01070071257bd3f57d1d9da2
    hash f0dff53969080584560b2971411415bdf9064d5a5a50185c4ae018943e7d5cbe f0dff53969080584560b2971411415bdf9064d5a5a50185c4ae018943e7d5cbe
    hash 94eb8da6703dd073184015c9e3cb34e9b6153fc499c9cb1a7db6e4361ec349dd 94eb8da6703dd073184015c9e3cb34e9b6153fc499c9cb1a7db6e4361ec349dd
    hash ac9dc55f13d973e05865e9674c8b8e6744e7fbfca3355199b292f614f13ac7bc ac9dc55f13d973e05865e9674c8b8e6744e7fbfca3355199b292f614f13ac7bc
    hash 190dbcafa776e8cc221106414b8fbd68252d98438c5e46b8449788fbe70316a4 190dbcafa776e8cc221106414b8fbd68252d98438c5e46b8449788fbe70316a4
    hash d565e3f03d0b1a7c8935d7ff94237316 d565e3f03d0b1a7c8935d7ff94237316
    file lib/net8.0/Sicoob.Sdk.dll lib/net8.0/Sicoob.Sdk.dll