Skip to content
Merged
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
30 changes: 27 additions & 3 deletions Dockerfile.scanner
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,33 @@ RUN CGO_ENABLED=0 make devguard-scanner
FROM alpine:3.22.1@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1

RUN apk add --no-cache git python3
RUN python3 -m venv /usr/local/bin/venv && \
/usr/local/bin/venv/bin/pip install --upgrade pip && \
/usr/local/bin/venv/bin/pip install semgrep checkov
# Create virtualenvs
ENV VENV_DIR=/opt/tools
RUN python -m venv ${VENV_DIR}/semgrep && \
python -m venv ${VENV_DIR}/checkov

# Install semgrep in its venv
RUN ${VENV_DIR}/semgrep/bin/pip install --upgrade pip && \
${VENV_DIR}/semgrep/bin/pip install semgrep==1.131.0

# Install checkov in its venv
RUN ${VENV_DIR}/checkov/bin/pip install --upgrade pip && \
${VENV_DIR}/checkov/bin/pip install checkov==3.2.457


RUN cat <<EOF > /usr/local/bin/semgrep
#!/bin/sh
exec ${VENV_DIR}/semgrep/bin/semgrep "\$@"
EOF

RUN chmod +x /usr/local/bin/semgrep

RUN cat <<EOF > /usr/local/bin/checkov
#!/bin/sh
exec ${VENV_DIR}/checkov/bin/checkov "\$@"
EOF

RUN chmod +x /usr/local/bin/checkov

# add venv bin to path
ENV PATH="/usr/local/bin/venv/bin:$PATH"
Expand Down
12 changes: 11 additions & 1 deletion internal/core/vuln/dependency_vuln_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"context"
"fmt"
"log/slog"
"slices"
"time"

"github.com/google/uuid"
Expand Down Expand Up @@ -105,7 +106,16 @@ func (s *service) UserDetectedExistingVulnOnDifferentBranch(tx core.DB, scannerI
ev := models.NewDetectedOnAnotherBranchEvent(dependencyVuln.CalculateHash(), models.VulnTypeDependencyVuln, "system", riskReport, scannerID, assetVersion.Name)
events[i] = append(events[i], ev)
// replay all events on the dependencyVuln
for _, ev := range alreadyExistingEvents[i] {
// but sort them by the time they were created ascending
slices.SortStableFunc(events[i], func(a, b models.VulnEvent) int {
if a.CreatedAt.Before(b.CreatedAt) {
return -1
} else if a.CreatedAt.After(b.CreatedAt) {
return 1
}
return 0
})
for _, ev := range events[i] {
ev.Apply(&dependencyVulns[i])
}
}
Expand Down
29 changes: 19 additions & 10 deletions internal/core/vulndb/scan/scan_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,6 @@ func TestScanning(t *testing.T) {
// should be only a single vulnerability
assert.Nil(t, err)
assert.Len(t, vulns, 1)
// mark the vuln as accepted
vulns[0].State = models.VulnStateAccepted
// save it
err = dependencyVulnRepository.Save(nil, &vulns[0])
assert.Nil(t, err)

// create an accepted event inside the database
acceptedEvent := models.NewAcceptedEvent(vulns[0].ID, vulns[0].GetType(), "abc", "accepting the vulnerability")
err = dependencyVulnRepository.ApplyAndSave(nil, &vulns[0], &acceptedEvent)
Expand Down Expand Up @@ -219,12 +213,27 @@ func TestScanning(t *testing.T) {
newVuln = v
}
}

assert.NotEmpty(t, newVuln.Events)
lastTwoEvents := newVuln.Events[len(newVuln.Events)-2:]
assert.Equal(t, models.EventTypeAccepted, lastTwoEvents[0].Type)
assert.Equal(t, "accepting the vulnerability", *lastTwoEvents[0].Justification)
assert.Equal(t, "main", *lastTwoEvents[0].OriginalAssetVersionName)
assert.Equal(t, models.EventTypeDetectedOnAnotherBranch, lastTwoEvents[1].Type)

// we can not really rely on the created_at since the events are created in the same second
// nevertheless - one has to be the accepted event and the other the detected on different branch event
var accEvent models.VulnEvent
var detectedOnAnotherBranchEvent models.VulnEvent
for _, ev := range lastTwoEvents {
if ev.Type == models.EventTypeAccepted {
accEvent = ev
} else {
detectedOnAnotherBranchEvent = ev
}
}

assert.NotEmpty(t, accEvent)
assert.NotEmpty(t, detectedOnAnotherBranchEvent)
assert.Equal(t, models.EventTypeAccepted, accEvent.Type)
assert.Equal(t, "accepting the vulnerability", *accEvent.Justification)
assert.Equal(t, "main", *accEvent.OriginalAssetVersionName)
})
}

Expand Down
4 changes: 3 additions & 1 deletion internal/database/repositories/vulnerability_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ func (r *VulnerabilityRepository[T]) GetByAssetID(

var vulns = []T{}
// get all vulnerabilities of the asset
if err := r.Repository.GetDB(tx).Where("asset_id = ?", assetID).Preload("Events").Find(&vulns).Error; err != nil {
if err := r.Repository.GetDB(tx).Where("asset_id = ?", assetID).Preload("Events", func(db *gorm.DB) *gorm.DB {
return db.Order("vuln_events.created_at ASC")
}).Find(&vulns).Error; err != nil {
return nil, err
}
return vulns, nil
Expand Down