feat(nadezhda): keyless CVE enrichment, folded into scrape, news-first ranking
This is a security-news tool; CVE enrichment is optional garnish, never a setup tax. Drop the NVD API key from the default path entirely. - internal/cve/cvelist: keyless CVE Program cvelistV5 client (raw GitHub, carries CISA-ADP / vulnrichment CVSS). Parses cna and adp metrics with version precedence v4.0 > v3.1 > v3.0 > v2.0, plus CWE and description; 404 maps to not-found; v2 severity is capped at HIGH. Introduces a neutral CoreResult and a CVESource interface (NVDResult renamed to CoreResult; NVDClient still satisfies it). - enrich: Clients.Core is the CVESource. buildCoreSource picks the keyless cvelist client by default and NVD only when NVD_API_KEY is set (booster). - scrape auto-enriches referenced CVEs best-effort after clustering (time-bounded, non-fatal, --no-enrich to skip); enrich kept as an optional manual refresh. Default flow is scrape -> tui. - ranking default weights rebalanced news-first (recency / velocity / source / keyword 70 percent, cvss / kev / epss 30 percent; was 55 percent CVE). - KAT fixture testdata/cvelist/CVE-2021-44228.json.
This commit is contained in:
parent
26651547e1
commit
41ffd49699
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/CarterPerez-dev/nadezhda/internal/config"
|
||||
"github.com/CarterPerez-dev/nadezhda/internal/cve"
|
||||
"github.com/CarterPerez-dev/nadezhda/internal/enrich"
|
||||
"github.com/CarterPerez-dev/nadezhda/internal/store"
|
||||
|
|
@ -22,7 +23,8 @@ const nvdAPIKeyEnv = "NVD_API_KEY"
|
|||
|
||||
var enrichCmd = &cobra.Command{
|
||||
Use: "enrich",
|
||||
Short: "Enrich extracted CVEs with NVD, CISA KEV, and EPSS intelligence",
|
||||
Short: "Refresh CVE intelligence (CVE List / NVD, CISA KEV, EPSS) for extracted CVEs",
|
||||
Long: "Refresh CVE intelligence for extracted CVEs. Keyless by default (CVE Program, CISA KEV, EPSS); uses NVD only when NVD_API_KEY is set. scrape already runs this automatically, so this command is for manually refreshing.",
|
||||
RunE: runEnrich,
|
||||
}
|
||||
|
||||
|
|
@ -41,27 +43,39 @@ func runEnrich(cmd *cobra.Command, args []string) error {
|
|||
}
|
||||
defer st.Close()
|
||||
|
||||
httpClient := &http.Client{Timeout: time.Duration(cfg.Fetch.TimeoutSeconds) * time.Second}
|
||||
apiKey := os.Getenv(nvdAPIKeyEnv)
|
||||
if apiKey == "" {
|
||||
apiKey = cfg.Enrich.NVDAPIKey
|
||||
}
|
||||
clients := enrich.Clients{
|
||||
NVD: cve.NewNVDClient(httpClient, cve.NVDEndpoint, apiKey),
|
||||
KEV: cve.NewKEVClient(httpClient, cve.KEVEndpoint),
|
||||
EPSS: cve.NewEPSSClient(httpClient, cve.EPSSEndpoint),
|
||||
}
|
||||
|
||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||
defer stop()
|
||||
|
||||
stats, err := enrich.Run(ctx, st, clients, time.Now(), cfg.Enrich.CacheTTLHours, cfg.Enrich.NegativeTTLHours)
|
||||
stats, err := enrich.Run(ctx, st, buildEnrichClients(cfg), time.Now(), cfg.Enrich.CacheTTLHours, cfg.Enrich.NegativeTTLHours)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(cmd.OutOrStdout(),
|
||||
"enriched %d/%d CVEs (%d not in NVD, %d KEV, %d errors)\n",
|
||||
"enriched %d/%d CVEs (%d not found, %d KEV, %d errors)\n",
|
||||
stats.Enriched, stats.Total, stats.NotFound, stats.KEVHits, stats.Errors)
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildEnrichClients(cfg config.Config) enrich.Clients {
|
||||
httpClient := &http.Client{Timeout: time.Duration(cfg.Fetch.TimeoutSeconds) * time.Second}
|
||||
return enrich.Clients{
|
||||
Core: buildCoreSource(httpClient, nvdAPIKey(cfg)),
|
||||
KEV: cve.NewKEVClient(httpClient, cve.KEVEndpoint),
|
||||
EPSS: cve.NewEPSSClient(httpClient, cve.EPSSEndpoint),
|
||||
}
|
||||
}
|
||||
|
||||
func buildCoreSource(httpClient *http.Client, apiKey string) cve.CVESource {
|
||||
if apiKey != "" {
|
||||
return cve.NewNVDClient(httpClient, cve.NVDEndpoint, apiKey)
|
||||
}
|
||||
return cve.NewCVEListClient(httpClient, cve.CVEListEndpoint)
|
||||
}
|
||||
|
||||
func nvdAPIKey(cfg config.Config) string {
|
||||
if k := os.Getenv(nvdAPIKeyEnv); k != "" {
|
||||
return k
|
||||
}
|
||||
return cfg.Enrich.NVDAPIKey
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/CarterPerez-dev/nadezhda/internal/cluster"
|
||||
"github.com/CarterPerez-dev/nadezhda/internal/config"
|
||||
"github.com/CarterPerez-dev/nadezhda/internal/enrich"
|
||||
"github.com/CarterPerez-dev/nadezhda/internal/fetch"
|
||||
"github.com/CarterPerez-dev/nadezhda/internal/ingest"
|
||||
"github.com/CarterPerez-dev/nadezhda/internal/source"
|
||||
|
|
@ -21,6 +23,8 @@ import (
|
|||
|
||||
const secondsPerHour = 3600
|
||||
|
||||
const enrichBudget = 5 * time.Minute
|
||||
|
||||
const (
|
||||
statusNotModified = "304"
|
||||
statusError = "error"
|
||||
|
|
@ -28,7 +32,10 @@ const (
|
|||
dash = "-"
|
||||
)
|
||||
|
||||
var scrapeSource string
|
||||
var (
|
||||
scrapeSource string
|
||||
scrapeNoEnrich bool
|
||||
)
|
||||
|
||||
var scrapeCmd = &cobra.Command{
|
||||
Use: "scrape",
|
||||
|
|
@ -38,6 +45,7 @@ var scrapeCmd = &cobra.Command{
|
|||
|
||||
func init() {
|
||||
scrapeCmd.Flags().StringVar(&scrapeSource, "source", "", "ingest only this source by name")
|
||||
scrapeCmd.Flags().BoolVar(&scrapeNoEnrich, "no-enrich", false, "skip the keyless CVE enrichment pass")
|
||||
rootCmd.AddCommand(scrapeCmd)
|
||||
}
|
||||
|
||||
|
|
@ -88,9 +96,34 @@ func runScrape(cmd *cobra.Command, args []string) error {
|
|||
}
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "%d clusters (%d multi-source, largest %d)\n",
|
||||
stats.Total, stats.MultiSource, stats.LargestSize)
|
||||
|
||||
if !scrapeNoEnrich {
|
||||
enrichAfterScrape(ctx, cmd, cfg, st)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func enrichAfterScrape(ctx context.Context, cmd *cobra.Command, cfg config.Config, st *store.Store) {
|
||||
out := cmd.OutOrStdout()
|
||||
ectx, cancel := context.WithTimeout(ctx, enrichBudget)
|
||||
defer cancel()
|
||||
|
||||
stats, err := enrich.Run(ectx, st, buildEnrichClients(cfg), time.Now(), cfg.Enrich.CacheTTLHours, cfg.Enrich.NegativeTTLHours)
|
||||
if err != nil {
|
||||
if done := stats.Enriched + stats.NotFound; done > 0 {
|
||||
fmt.Fprintf(out, "enriched %d/%d CVEs before stopping: %v\n", done, stats.Total, err)
|
||||
} else {
|
||||
fmt.Fprintf(out, "enrich skipped: %v (news is unaffected)\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if stats.Total == 0 {
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(out, "enriched %d/%d CVEs (%d KEV, %d not found)\n",
|
||||
stats.Enriched, stats.Total, stats.KEVHits, stats.NotFound)
|
||||
}
|
||||
|
||||
func selectTargets(srcs []source.Source, only string) ([]source.Source, error) {
|
||||
if only != "" {
|
||||
for _, s := range srcs {
|
||||
|
|
|
|||
|
|
@ -33,13 +33,13 @@ const (
|
|||
defaultHalfLifeHours = 48
|
||||
defaultVelocityNorm = 0.5
|
||||
|
||||
defaultWeightRecency = 0.20
|
||||
defaultWeightCVSS = 0.15
|
||||
defaultWeightKEV = 0.25
|
||||
defaultWeightEPSS = 0.15
|
||||
defaultWeightVelocity = 0.15
|
||||
defaultWeightSource = 0.05
|
||||
defaultWeightKeyword = 0.05
|
||||
defaultWeightRecency = 0.30
|
||||
defaultWeightVelocity = 0.20
|
||||
defaultWeightKEV = 0.12
|
||||
defaultWeightCVSS = 0.10
|
||||
defaultWeightSource = 0.10
|
||||
defaultWeightKeyword = 0.10
|
||||
defaultWeightEPSS = 0.08
|
||||
|
||||
defaultAIProvider = "qwen"
|
||||
defaultQwenBaseURL = "http://localhost:11434/v1"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,249 @@
|
|||
// ©AngelaMos | 2026
|
||||
// cvelist.go
|
||||
|
||||
package cve
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
const (
|
||||
CVEListEndpoint = "https://raw.githubusercontent.com/CVEProject/cvelistV5/main/cves"
|
||||
|
||||
cvelistRate = 15
|
||||
cvelistMaxRetries = 2
|
||||
cvelistBackoff = time.Second
|
||||
cvelistBucketTail = 3
|
||||
cveIDParts = 3
|
||||
langEnPrefix = "en"
|
||||
|
||||
cvssCriticalMin = 9.0
|
||||
cvssHighMin = 7.0
|
||||
cvssMediumMin = 4.0
|
||||
|
||||
cvssVersion2Prefix = "2"
|
||||
|
||||
sevCritical = "CRITICAL"
|
||||
sevHigh = "HIGH"
|
||||
sevMedium = "MEDIUM"
|
||||
sevLow = "LOW"
|
||||
sevNone = "NONE"
|
||||
)
|
||||
|
||||
type CoreResult struct {
|
||||
Found bool
|
||||
Description string
|
||||
CVSSScore *float64
|
||||
CVSSVersion string
|
||||
CVSSSeverity string
|
||||
CVSSVector string
|
||||
CWE string
|
||||
Published string
|
||||
Modified string
|
||||
}
|
||||
|
||||
type CVESource interface {
|
||||
Fetch(ctx context.Context, cveID string) (CoreResult, error)
|
||||
}
|
||||
|
||||
type CVEListClient struct {
|
||||
http *http.Client
|
||||
baseURL string
|
||||
limiter *rate.Limiter
|
||||
backoffBase time.Duration
|
||||
}
|
||||
|
||||
func NewCVEListClient(client *http.Client, baseURL string) *CVEListClient {
|
||||
return &CVEListClient{
|
||||
http: client,
|
||||
baseURL: strings.TrimRight(baseURL, "/"),
|
||||
limiter: rate.NewLimiter(rate.Limit(cvelistRate), 1),
|
||||
backoffBase: cvelistBackoff,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CVEListClient) Fetch(ctx context.Context, cveID string) (CoreResult, error) {
|
||||
endpoint, err := c.recordURL(cveID)
|
||||
if err != nil {
|
||||
return CoreResult{}, err
|
||||
}
|
||||
|
||||
var rec cvelistRecord
|
||||
for attempt := 0; attempt <= cvelistMaxRetries; attempt++ {
|
||||
if attempt > 0 {
|
||||
if err := sleep(ctx, c.backoffBase*time.Duration(1<<(attempt-1))); err != nil {
|
||||
return CoreResult{}, err
|
||||
}
|
||||
}
|
||||
if err := c.limiter.Wait(ctx); err != nil {
|
||||
return CoreResult{}, err
|
||||
}
|
||||
err := getJSON(ctx, c.http, endpoint, nil, &rec)
|
||||
if err == nil {
|
||||
return rec.toResult(), nil
|
||||
}
|
||||
var se *statusError
|
||||
if errors.As(err, &se) && se.code == http.StatusNotFound {
|
||||
return CoreResult{Found: false}, nil
|
||||
}
|
||||
if !retriable(err) || attempt == cvelistMaxRetries {
|
||||
return CoreResult{}, err
|
||||
}
|
||||
}
|
||||
return CoreResult{Found: false}, nil
|
||||
}
|
||||
|
||||
func (c *CVEListClient) recordURL(cveID string) (string, error) {
|
||||
parts := strings.Split(cveID, "-")
|
||||
if len(parts) != cveIDParts || parts[0] != "CVE" {
|
||||
return "", fmt.Errorf("cve: malformed id %q", cveID)
|
||||
}
|
||||
num := parts[2]
|
||||
if len(num) <= cvelistBucketTail {
|
||||
return "", fmt.Errorf("cve: short id %q", cveID)
|
||||
}
|
||||
bucket := num[:len(num)-cvelistBucketTail] + "xxx"
|
||||
return fmt.Sprintf("%s/%s/%s/%s.json", c.baseURL, parts[1], bucket, cveID), nil
|
||||
}
|
||||
|
||||
type cvelistRecord struct {
|
||||
CVEMetadata struct {
|
||||
DatePublished string `json:"datePublished"`
|
||||
DateUpdated string `json:"dateUpdated"`
|
||||
} `json:"cveMetadata"`
|
||||
Containers struct {
|
||||
CNA cvelistContainer `json:"cna"`
|
||||
ADP []cvelistContainer `json:"adp"`
|
||||
} `json:"containers"`
|
||||
}
|
||||
|
||||
type cvelistContainer struct {
|
||||
Descriptions []cvelistLangValue `json:"descriptions"`
|
||||
ProblemTypes []struct {
|
||||
Descriptions []struct {
|
||||
Lang string `json:"lang"`
|
||||
CweID string `json:"cweId"`
|
||||
} `json:"descriptions"`
|
||||
} `json:"problemTypes"`
|
||||
Metrics []cvelistMetric `json:"metrics"`
|
||||
}
|
||||
|
||||
type cvelistLangValue struct {
|
||||
Lang string `json:"lang"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type cvelistMetric struct {
|
||||
V40 *cvelistCVSS `json:"cvssV4_0"`
|
||||
V31 *cvelistCVSS `json:"cvssV3_1"`
|
||||
V30 *cvelistCVSS `json:"cvssV3_0"`
|
||||
V2 *cvelistCVSS `json:"cvssV2_0"`
|
||||
}
|
||||
|
||||
type cvelistCVSS struct {
|
||||
Version string `json:"version"`
|
||||
BaseScore float64 `json:"baseScore"`
|
||||
BaseSeverity string `json:"baseSeverity"`
|
||||
VectorString string `json:"vectorString"`
|
||||
}
|
||||
|
||||
func (rec cvelistRecord) containers() []cvelistContainer {
|
||||
out := make([]cvelistContainer, 0, len(rec.Containers.ADP)+1)
|
||||
out = append(out, rec.Containers.CNA)
|
||||
out = append(out, rec.Containers.ADP...)
|
||||
return out
|
||||
}
|
||||
|
||||
func (rec cvelistRecord) toResult() CoreResult {
|
||||
res := CoreResult{
|
||||
Found: true,
|
||||
Description: rec.description(),
|
||||
CWE: rec.cwe(),
|
||||
Published: rec.CVEMetadata.DatePublished,
|
||||
Modified: rec.CVEMetadata.DateUpdated,
|
||||
}
|
||||
if cv := rec.cvss(); cv != nil {
|
||||
score := cv.BaseScore
|
||||
res.CVSSScore = &score
|
||||
res.CVSSVersion = cv.Version
|
||||
res.CVSSVector = cv.VectorString
|
||||
res.CVSSSeverity = cv.BaseSeverity
|
||||
if res.CVSSSeverity == "" {
|
||||
res.CVSSSeverity = severityFromScore(score, cv.Version)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (rec cvelistRecord) cvss() *cvelistCVSS {
|
||||
tiers := []func(cvelistMetric) *cvelistCVSS{
|
||||
func(m cvelistMetric) *cvelistCVSS { return m.V40 },
|
||||
func(m cvelistMetric) *cvelistCVSS { return m.V31 },
|
||||
func(m cvelistMetric) *cvelistCVSS { return m.V30 },
|
||||
func(m cvelistMetric) *cvelistCVSS { return m.V2 },
|
||||
}
|
||||
containers := rec.containers()
|
||||
for _, pick := range tiers {
|
||||
for _, c := range containers {
|
||||
for _, m := range c.Metrics {
|
||||
if cv := pick(m); cv != nil {
|
||||
return cv
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rec cvelistRecord) cwe() string {
|
||||
for _, c := range rec.containers() {
|
||||
for _, pt := range c.ProblemTypes {
|
||||
for _, d := range pt.Descriptions {
|
||||
if d.CweID != "" {
|
||||
return d.CweID
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (rec cvelistRecord) description() string {
|
||||
for _, c := range rec.containers() {
|
||||
for _, d := range c.Descriptions {
|
||||
if strings.HasPrefix(d.Lang, langEnPrefix) && strings.TrimSpace(d.Value) != "" {
|
||||
return d.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, c := range rec.containers() {
|
||||
for _, d := range c.Descriptions {
|
||||
if strings.TrimSpace(d.Value) != "" {
|
||||
return d.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func severityFromScore(score float64, version string) string {
|
||||
switch {
|
||||
case score <= 0:
|
||||
return sevNone
|
||||
case score >= cvssCriticalMin && !strings.HasPrefix(version, cvssVersion2Prefix):
|
||||
return sevCritical
|
||||
case score >= cvssHighMin:
|
||||
return sevHigh
|
||||
case score >= cvssMediumMin:
|
||||
return sevMedium
|
||||
default:
|
||||
return sevLow
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
// ©AngelaMos | 2026
|
||||
// cvelist_test.go
|
||||
|
||||
package cve
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCVEListParsesLog4Shell(t *testing.T) {
|
||||
body, err := os.ReadFile("../../testdata/cvelist/CVE-2021-44228.json")
|
||||
if err != nil {
|
||||
t.Fatalf("read fixture: %v", err)
|
||||
}
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, _ = w.Write(body)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
client := NewCVEListClient(srv.Client(), srv.URL)
|
||||
res, err := client.Fetch(context.Background(), "CVE-2021-44228")
|
||||
if err != nil {
|
||||
t.Fatalf("Fetch: %v", err)
|
||||
}
|
||||
if !res.Found {
|
||||
t.Fatal("Found = false, want true")
|
||||
}
|
||||
if res.CVSSScore == nil || *res.CVSSScore != 10.0 {
|
||||
t.Errorf("CVSSScore = %v, want 10.0", res.CVSSScore)
|
||||
}
|
||||
if res.CVSSVersion != "3.1" || res.CVSSSeverity != "CRITICAL" {
|
||||
t.Errorf("cvss = %q/%q, want 3.1/CRITICAL", res.CVSSVersion, res.CVSSSeverity)
|
||||
}
|
||||
if res.CVSSVector != "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H" {
|
||||
t.Errorf("vector = %q", res.CVSSVector)
|
||||
}
|
||||
if res.CWE != "CWE-502" {
|
||||
t.Errorf("CWE = %q, want CWE-502 (first problemType)", res.CWE)
|
||||
}
|
||||
if !strings.Contains(res.Description, "Log4j") {
|
||||
t.Errorf("description missing Log4j: %q", res.Description)
|
||||
}
|
||||
if res.Published == "" || res.Modified == "" {
|
||||
t.Errorf("published/modified empty: %q / %q", res.Published, res.Modified)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCVEListNotFound(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
client := NewCVEListClient(srv.Client(), srv.URL)
|
||||
res, err := client.Fetch(context.Background(), "CVE-2099-99999")
|
||||
if err != nil {
|
||||
t.Fatalf("Fetch: %v", err)
|
||||
}
|
||||
if res.Found {
|
||||
t.Error("Found = true on 404, want false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCVEListRecordURL(t *testing.T) {
|
||||
client := NewCVEListClient(http.DefaultClient, "https://example.com/cves")
|
||||
cases := map[string]string{
|
||||
"CVE-2021-44228": "https://example.com/cves/2021/44xxx/CVE-2021-44228.json",
|
||||
"CVE-2021-1234": "https://example.com/cves/2021/1xxx/CVE-2021-1234.json",
|
||||
"CVE-2023-12345": "https://example.com/cves/2023/12xxx/CVE-2023-12345.json",
|
||||
}
|
||||
for id, want := range cases {
|
||||
got, err := client.recordURL(id)
|
||||
if err != nil {
|
||||
t.Errorf("recordURL(%q): %v", id, err)
|
||||
continue
|
||||
}
|
||||
if got != want {
|
||||
t.Errorf("recordURL(%q) = %q, want %q", id, got, want)
|
||||
}
|
||||
}
|
||||
if _, err := client.recordURL("not-a-cve"); err == nil {
|
||||
t.Error("expected error for malformed id")
|
||||
}
|
||||
if _, err := client.recordURL("CVE-2021-12"); err == nil {
|
||||
t.Error("expected error for a too-short cve number")
|
||||
}
|
||||
}
|
||||
|
||||
func serveJSON(t *testing.T, body string) *httptest.Server {
|
||||
t.Helper()
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, _ = w.Write([]byte(body))
|
||||
}))
|
||||
t.Cleanup(srv.Close)
|
||||
return srv
|
||||
}
|
||||
|
||||
func TestCVEListCNAMetrics(t *testing.T) {
|
||||
srv := serveJSON(t, `{"cveMetadata":{"datePublished":"2020-01-01T00:00:00Z","dateUpdated":"2020-02-01T00:00:00Z"},"containers":{"cna":{"descriptions":[{"lang":"en","value":"cna container path"}],"problemTypes":[{"descriptions":[{"lang":"en","cweId":"CWE-79"}]}],"metrics":[{"cvssV3_1":{"version":"3.1","baseScore":7.5,"baseSeverity":"HIGH","vectorString":"CVSS:3.1/AV:N/AC:L"}}]}}}`)
|
||||
res, err := NewCVEListClient(srv.Client(), srv.URL).Fetch(context.Background(), "CVE-2020-0001")
|
||||
if err != nil {
|
||||
t.Fatalf("Fetch: %v", err)
|
||||
}
|
||||
if res.CVSSScore == nil || *res.CVSSScore != 7.5 || res.CVSSVersion != "3.1" || res.CVSSSeverity != "HIGH" {
|
||||
t.Errorf("cna metrics = %v/%q/%q, want 7.5/3.1/HIGH", res.CVSSScore, res.CVSSVersion, res.CVSSSeverity)
|
||||
}
|
||||
if res.CWE != "CWE-79" {
|
||||
t.Errorf("CWE = %q, want CWE-79", res.CWE)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCVEListV2SeverityNotCritical(t *testing.T) {
|
||||
srv := serveJSON(t, `{"cveMetadata":{"datePublished":"2005-01-01T00:00:00Z","dateUpdated":"2005-01-01T00:00:00Z"},"containers":{"cna":{"descriptions":[{"lang":"en","value":"v2 only"}],"metrics":[{"cvssV2_0":{"version":"2.0","baseScore":9.0,"vectorString":"AV:N/AC:L/Au:N/C:C/I:C/A:C"}}]}}}`)
|
||||
res, err := NewCVEListClient(srv.Client(), srv.URL).Fetch(context.Background(), "CVE-2005-0001")
|
||||
if err != nil {
|
||||
t.Fatalf("Fetch: %v", err)
|
||||
}
|
||||
if res.CVSSVersion != "2.0" || res.CVSSScore == nil || *res.CVSSScore != 9.0 {
|
||||
t.Errorf("v2 = %q/%v, want 2.0/9.0", res.CVSSVersion, res.CVSSScore)
|
||||
}
|
||||
if res.CVSSSeverity != "HIGH" {
|
||||
t.Errorf("v2 severity = %q, want HIGH (CVSS v2 has no CRITICAL tier)", res.CVSSSeverity)
|
||||
}
|
||||
}
|
||||
|
||||
var _ CVESource = (*CVEListClient)(nil)
|
||||
var _ CVESource = (*NVDClient)(nil)
|
||||
|
|
@ -24,18 +24,6 @@ const (
|
|||
langEnglish = "en"
|
||||
)
|
||||
|
||||
type NVDResult struct {
|
||||
Found bool
|
||||
Description string
|
||||
CVSSScore *float64
|
||||
CVSSVersion string
|
||||
CVSSSeverity string
|
||||
CVSSVector string
|
||||
CWE string
|
||||
Published string
|
||||
Modified string
|
||||
}
|
||||
|
||||
type NVDClient struct {
|
||||
http *http.Client
|
||||
baseURL string
|
||||
|
|
@ -58,7 +46,7 @@ func NewNVDClient(client *http.Client, baseURL, apiKey string) *NVDClient {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *NVDClient) Fetch(ctx context.Context, cveID string) (NVDResult, error) {
|
||||
func (c *NVDClient) Fetch(ctx context.Context, cveID string) (CoreResult, error) {
|
||||
endpoint := c.baseURL + "?" + url.Values{"cveId": {cveID}}.Encode()
|
||||
header := http.Header{}
|
||||
if c.apiKey != "" {
|
||||
|
|
@ -69,23 +57,23 @@ func (c *NVDClient) Fetch(ctx context.Context, cveID string) (NVDResult, error)
|
|||
for attempt := 0; attempt <= nvdMaxRetries; attempt++ {
|
||||
if attempt > 0 {
|
||||
if err := sleep(ctx, c.backoffBase*time.Duration(1<<(attempt-1))); err != nil {
|
||||
return NVDResult{}, err
|
||||
return CoreResult{}, err
|
||||
}
|
||||
}
|
||||
if err := c.limiter.Wait(ctx); err != nil {
|
||||
return NVDResult{}, err
|
||||
return CoreResult{}, err
|
||||
}
|
||||
err := getJSON(ctx, c.http, endpoint, header, &env)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if !retriable(err) || attempt == nvdMaxRetries {
|
||||
return NVDResult{}, err
|
||||
return CoreResult{}, err
|
||||
}
|
||||
}
|
||||
|
||||
if env.TotalResults == 0 || len(env.Vulnerabilities) == 0 {
|
||||
return NVDResult{Found: false}, nil
|
||||
return CoreResult{Found: false}, nil
|
||||
}
|
||||
return env.Vulnerabilities[0].CVE.toResult(), nil
|
||||
}
|
||||
|
|
@ -140,8 +128,8 @@ type nvdCVSSData struct {
|
|||
BaseSeverity string `json:"baseSeverity"`
|
||||
}
|
||||
|
||||
func (v nvdCVE) toResult() NVDResult {
|
||||
res := NVDResult{
|
||||
func (v nvdCVE) toResult() CoreResult {
|
||||
res := CoreResult{
|
||||
Found: true,
|
||||
Description: english(v.Descriptions),
|
||||
Published: v.Published,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import (
|
|||
const secondsPerHour = 3600
|
||||
|
||||
type Clients struct {
|
||||
NVD *cve.NVDClient
|
||||
Core cve.CVESource
|
||||
KEV *cve.KEVClient
|
||||
EPSS *cve.EPSSClient
|
||||
}
|
||||
|
|
@ -51,7 +51,7 @@ func Run(ctx context.Context, st *store.Store, clients Clients, now time.Time, p
|
|||
|
||||
stats := Stats{Total: len(ids)}
|
||||
for _, id := range ids {
|
||||
nvdRes, err := clients.NVD.Fetch(ctx, id)
|
||||
coreRes, err := clients.Core.Fetch(ctx, id)
|
||||
if err != nil {
|
||||
if ctx.Err() != nil {
|
||||
return stats, ctx.Err()
|
||||
|
|
@ -61,16 +61,16 @@ func Run(ctx context.Context, st *store.Store, clients Clients, now time.Time, p
|
|||
}
|
||||
|
||||
rec := store.CVE{ID: id, EnrichedAt: now.Unix()}
|
||||
if nvdRes.Found {
|
||||
if coreRes.Found {
|
||||
rec.EnrichStatus = store.EnrichStatusOK
|
||||
rec.Description = nvdRes.Description
|
||||
rec.CVSSScore = nvdRes.CVSSScore
|
||||
rec.CVSSVersion = nvdRes.CVSSVersion
|
||||
rec.CVSSSeverity = nvdRes.CVSSSeverity
|
||||
rec.CVSSVector = nvdRes.CVSSVector
|
||||
rec.CWE = nvdRes.CWE
|
||||
rec.NVDPublished = nvdRes.Published
|
||||
rec.NVDModified = nvdRes.Modified
|
||||
rec.Description = coreRes.Description
|
||||
rec.CVSSScore = coreRes.CVSSScore
|
||||
rec.CVSSVersion = coreRes.CVSSVersion
|
||||
rec.CVSSSeverity = coreRes.CVSSSeverity
|
||||
rec.CVSSVector = coreRes.CVSSVector
|
||||
rec.CWE = coreRes.CWE
|
||||
rec.NVDPublished = coreRes.Published
|
||||
rec.NVDModified = coreRes.Modified
|
||||
} else {
|
||||
rec.EnrichStatus = store.EnrichStatusNotFound
|
||||
}
|
||||
|
|
@ -92,7 +92,7 @@ func Run(ctx context.Context, st *store.Store, clients Clients, now time.Time, p
|
|||
stats.Errors++
|
||||
continue
|
||||
}
|
||||
if nvdRes.Found {
|
||||
if coreRes.Found {
|
||||
stats.Enriched++
|
||||
} else {
|
||||
stats.NotFound++
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ func TestRunEnrichesLog4Shell(t *testing.T) {
|
|||
}
|
||||
|
||||
clients := Clients{
|
||||
NVD: cve.NewNVDClient(nvd.Client(), nvd.URL, ""),
|
||||
Core: cve.NewNVDClient(nvd.Client(), nvd.URL, ""),
|
||||
KEV: cve.NewKEVClient(kev.Client(), kev.URL),
|
||||
EPSS: cve.NewEPSSClient(epss.Client(), epss.URL),
|
||||
}
|
||||
|
|
@ -97,7 +97,7 @@ func TestRunSkipsFreshAndMarksNotFound(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
clients := Clients{
|
||||
NVD: cve.NewNVDClient(nvd.Client(), nvd.URL, ""),
|
||||
Core: cve.NewNVDClient(nvd.Client(), nvd.URL, ""),
|
||||
KEV: cve.NewKEVClient(kev.Client(), kev.URL),
|
||||
EPSS: cve.NewEPSSClient(epss.Client(), epss.URL),
|
||||
}
|
||||
|
|
|
|||
796
PROJECTS/intermediate/security-news-scraper/testdata/cvelist/CVE-2021-44228.json
vendored
Normal file
796
PROJECTS/intermediate/security-news-scraper/testdata/cvelist/CVE-2021-44228.json
vendored
Normal file
|
|
@ -0,0 +1,796 @@
|
|||
{
|
||||
"dataType": "CVE_RECORD",
|
||||
"dataVersion": "5.1",
|
||||
"cveMetadata": {
|
||||
"state": "PUBLISHED",
|
||||
"cveId": "CVE-2021-44228",
|
||||
"assignerOrgId": "f0158376-9dc2-43b6-827c-5f631a4d8d09",
|
||||
"assignerShortName": "apache",
|
||||
"dateUpdated": "2025-10-21T23:25:23.121Z",
|
||||
"dateReserved": "2021-11-26T00:00:00.000Z",
|
||||
"datePublished": "2021-12-10T00:00:00.000Z"
|
||||
},
|
||||
"containers": {
|
||||
"cna": {
|
||||
"title": "Apache Log4j2 JNDI features do not protect against attacker controlled LDAP and other JNDI related endpoints",
|
||||
"providerMetadata": {
|
||||
"orgId": "f0158376-9dc2-43b6-827c-5f631a4d8d09",
|
||||
"shortName": "apache",
|
||||
"dateUpdated": "2023-04-03T00:00:00.000Z"
|
||||
},
|
||||
"descriptions": [
|
||||
{
|
||||
"lang": "en",
|
||||
"value": "Apache Log4j2 2.0-beta9 through 2.15.0 (excluding security releases 2.12.2, 2.12.3, and 2.3.1) JNDI features used in configuration, log messages, and parameters do not protect against attacker controlled LDAP and other JNDI related endpoints. An attacker who can control log messages or log message parameters can execute arbitrary code loaded from LDAP servers when message lookup substitution is enabled. From log4j 2.15.0, this behavior has been disabled by default. From version 2.16.0 (along with 2.12.2, 2.12.3, and 2.3.1), this functionality has been completely removed. Note that this vulnerability is specific to log4j-core and does not affect log4net, log4cxx, or other Apache Logging Services projects."
|
||||
}
|
||||
],
|
||||
"affected": [
|
||||
{
|
||||
"vendor": "Apache Software Foundation",
|
||||
"product": "Apache Log4j2",
|
||||
"versions": [
|
||||
{
|
||||
"version": "2.0-beta9",
|
||||
"status": "affected",
|
||||
"lessThan": "log4j-core*",
|
||||
"versionType": "custom",
|
||||
"changes": [
|
||||
{
|
||||
"at": "2.3.1",
|
||||
"status": "unaffected"
|
||||
},
|
||||
{
|
||||
"at": "2.4",
|
||||
"status": "affected"
|
||||
},
|
||||
{
|
||||
"at": "2.12.2",
|
||||
"status": "unaffected"
|
||||
},
|
||||
{
|
||||
"at": "2.13.0",
|
||||
"status": "affected"
|
||||
},
|
||||
{
|
||||
"at": "2.15.0",
|
||||
"status": "unaffected"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"url": "https://logging.apache.org/log4j/2.x/security.html"
|
||||
},
|
||||
{
|
||||
"name": "[oss-security] 20211210 CVE-2021-44228: Apache Log4j2 JNDI features do not protect against attacker controlled LDAP and other JNDI related endpoints",
|
||||
"tags": [
|
||||
"mailing-list"
|
||||
],
|
||||
"url": "http://www.openwall.com/lists/oss-security/2021/12/10/1"
|
||||
},
|
||||
{
|
||||
"name": "[oss-security] 20211210 Re: CVE-2021-44228: Apache Log4j2 JNDI features do not protect against attacker controlled LDAP and other JNDI related endpoints",
|
||||
"tags": [
|
||||
"mailing-list"
|
||||
],
|
||||
"url": "http://www.openwall.com/lists/oss-security/2021/12/10/2"
|
||||
},
|
||||
{
|
||||
"name": "20211210 Vulnerability in Apache Log4j Library Affecting Cisco Products: December 2021",
|
||||
"tags": [
|
||||
"vendor-advisory"
|
||||
],
|
||||
"url": "https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-apache-log4j-qRuKNEbd"
|
||||
},
|
||||
{
|
||||
"name": "[oss-security] 20211210 Re: CVE-2021-44228: Apache Log4j2 JNDI features do not protect against attacker controlled LDAP and other JNDI related endpoints",
|
||||
"tags": [
|
||||
"mailing-list"
|
||||
],
|
||||
"url": "http://www.openwall.com/lists/oss-security/2021/12/10/3"
|
||||
},
|
||||
{
|
||||
"url": "https://security.netapp.com/advisory/ntap-20211210-0007/"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165225/Apache-Log4j2-2.14.1-Remote-Code-Execution.html"
|
||||
},
|
||||
{
|
||||
"url": "https://psirt.global.sonicwall.com/vuln-detail/SNWLID-2021-0032"
|
||||
},
|
||||
{
|
||||
"url": "https://www.oracle.com/security-alerts/alert-cve-2021-44228.html"
|
||||
},
|
||||
{
|
||||
"name": "DSA-5020",
|
||||
"tags": [
|
||||
"vendor-advisory"
|
||||
],
|
||||
"url": "https://www.debian.org/security/2021/dsa-5020"
|
||||
},
|
||||
{
|
||||
"name": "[debian-lts-announce] 20211212 [SECURITY] [DLA 2842-1] apache-log4j2 security update",
|
||||
"tags": [
|
||||
"mailing-list"
|
||||
],
|
||||
"url": "https://lists.debian.org/debian-lts-announce/2021/12/msg00007.html"
|
||||
},
|
||||
{
|
||||
"name": "FEDORA-2021-f0f501d01f",
|
||||
"tags": [
|
||||
"vendor-advisory"
|
||||
],
|
||||
"url": "https://lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/VU57UJDCFIASIO35GC55JMKSRXJMCDFM/"
|
||||
},
|
||||
{
|
||||
"name": "Microsoft’s Response to CVE-2021-44228 Apache Log4j 2",
|
||||
"tags": [
|
||||
"vendor-advisory"
|
||||
],
|
||||
"url": "https://msrc-blog.microsoft.com/2021/12/11/microsofts-response-to-cve-2021-44228-apache-log4j2/"
|
||||
},
|
||||
{
|
||||
"name": "[oss-security] 20211213 Re: CVE-2021-4104: Deserialization of untrusted data in JMSAppender in Apache Log4j 1.2",
|
||||
"tags": [
|
||||
"mailing-list"
|
||||
],
|
||||
"url": "http://www.openwall.com/lists/oss-security/2021/12/13/2"
|
||||
},
|
||||
{
|
||||
"name": "[oss-security] 20211213 CVE-2021-4104: Deserialization of untrusted data in JMSAppender in Apache Log4j 1.2",
|
||||
"tags": [
|
||||
"mailing-list"
|
||||
],
|
||||
"url": "http://www.openwall.com/lists/oss-security/2021/12/13/1"
|
||||
},
|
||||
{
|
||||
"name": "[oss-security] 20211214 CVE-2021-45046: Apache Log4j2 Thread Context Message Pattern and Context Lookup Pattern vulnerable to a denial of service attack",
|
||||
"tags": [
|
||||
"mailing-list"
|
||||
],
|
||||
"url": "http://www.openwall.com/lists/oss-security/2021/12/14/4"
|
||||
},
|
||||
{
|
||||
"name": "20211210 A Vulnerability in Apache Log4j Library Affecting Cisco Products: December 2021",
|
||||
"tags": [
|
||||
"vendor-advisory"
|
||||
],
|
||||
"url": "https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-apache-log4j-qRuKNEbd"
|
||||
},
|
||||
{
|
||||
"name": "VU#930724",
|
||||
"tags": [
|
||||
"third-party-advisory"
|
||||
],
|
||||
"url": "https://www.kb.cert.org/vuls/id/930724"
|
||||
},
|
||||
{
|
||||
"url": "https://twitter.com/kurtseifried/status/1469345530182455296"
|
||||
},
|
||||
{
|
||||
"url": "https://cert-portal.siemens.com/productcert/pdf/ssa-661247.pdf"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165260/VMware-Security-Advisory-2021-0028.html"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165270/Apache-Log4j2-2.14.1-Remote-Code-Execution.html"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165261/Apache-Log4j2-2.14.1-Information-Disclosure.html"
|
||||
},
|
||||
{
|
||||
"url": "https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00646.html"
|
||||
},
|
||||
{
|
||||
"name": "20211210 Vulnerabilities in Apache Log4j Library Affecting Cisco Products: December 2021",
|
||||
"tags": [
|
||||
"vendor-advisory"
|
||||
],
|
||||
"url": "https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-apache-log4j-qRuKNEbd"
|
||||
},
|
||||
{
|
||||
"name": "[oss-security] 20211215 Re: CVE-2021-45046: Apache Log4j2 Thread Context Message Pattern and Context Lookup Pattern vulnerable to a denial of service attack",
|
||||
"tags": [
|
||||
"mailing-list"
|
||||
],
|
||||
"url": "http://www.openwall.com/lists/oss-security/2021/12/15/3"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165282/Log4j-Payload-Generator.html"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165281/Log4j2-Log4Shell-Regexes.html"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165307/Log4j-Remote-Code-Execution-Word-Bypassing.html"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165311/log4j-scan-Extensive-Scanner.html"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165306/L4sh-Log4j-Remote-Code-Execution.html"
|
||||
},
|
||||
{
|
||||
"url": "https://cert-portal.siemens.com/productcert/pdf/ssa-714170.pdf"
|
||||
},
|
||||
{
|
||||
"name": "FEDORA-2021-66d6c484f3",
|
||||
"tags": [
|
||||
"vendor-advisory"
|
||||
],
|
||||
"url": "https://lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/M5CSVUNV4HWZZXGOKNSK6L7RPM7BOKIB/"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165371/VMware-Security-Advisory-2021-0028.4.html"
|
||||
},
|
||||
{
|
||||
"url": "https://cert-portal.siemens.com/productcert/pdf/ssa-397453.pdf"
|
||||
},
|
||||
{
|
||||
"url": "https://cert-portal.siemens.com/productcert/pdf/ssa-479842.pdf"
|
||||
},
|
||||
{
|
||||
"url": "https://www.oracle.com/security-alerts/cpujan2022.html"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165532/Log4Shell-HTTP-Header-Injection.html"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/cisagov/log4j-affected-db/blob/develop/SOFTWARE-LIST.md"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165642/VMware-vCenter-Server-Unauthenticated-Log4Shell-JNDI-Injection-Remote-Code-Execution.html"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165673/UniFi-Network-Application-Unauthenticated-Log4Shell-Remote-Code-Execution.html"
|
||||
},
|
||||
{
|
||||
"name": "20220314 APPLE-SA-2022-03-14-7 Xcode 13.3",
|
||||
"tags": [
|
||||
"mailing-list"
|
||||
],
|
||||
"url": "http://seclists.org/fulldisclosure/2022/Mar/23"
|
||||
},
|
||||
{
|
||||
"url": "https://www.bentley.com/en/common-vulnerability-exposure/be-2022-0001"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/cisagov/log4j-affected-db"
|
||||
},
|
||||
{
|
||||
"url": "https://support.apple.com/kb/HT213189"
|
||||
},
|
||||
{
|
||||
"url": "https://www.oracle.com/security-alerts/cpuapr2022.html"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nu11secur1ty/CVE-mitre/tree/main/CVE-2021-44228"
|
||||
},
|
||||
{
|
||||
"url": "https://www.nu11secur1ty.com/2021/12/cve-2021-44228.html"
|
||||
},
|
||||
{
|
||||
"name": "20220721 Open-Xchange Security Advisory 2022-07-21",
|
||||
"tags": [
|
||||
"mailing-list"
|
||||
],
|
||||
"url": "http://seclists.org/fulldisclosure/2022/Jul/11"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/167794/Open-Xchange-App-Suite-7.10.x-Cross-Site-Scripting-Command-Injection.html"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/167917/MobileIron-Log4Shell-Remote-Command-Execution.html"
|
||||
},
|
||||
{
|
||||
"name": "20221208 Intel Data Center Manager <= 5.1 Local Privileges Escalation",
|
||||
"tags": [
|
||||
"mailing-list"
|
||||
],
|
||||
"url": "http://seclists.org/fulldisclosure/2022/Dec/2"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/171626/AD-Manager-Plus-7122-Remote-Code-Execution.html"
|
||||
}
|
||||
],
|
||||
"credits": [
|
||||
{
|
||||
"lang": "en",
|
||||
"value": "This issue was discovered by Chen Zhaojun of Alibaba Cloud Security Team."
|
||||
}
|
||||
],
|
||||
"metrics": [
|
||||
{
|
||||
"other": {
|
||||
"type": "unknown",
|
||||
"content": {
|
||||
"other": "critical"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"problemTypes": [
|
||||
{
|
||||
"descriptions": [
|
||||
{
|
||||
"type": "CWE",
|
||||
"lang": "en",
|
||||
"description": "CWE-502 Deserialization of Untrusted Data",
|
||||
"cweId": "CWE-502"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"descriptions": [
|
||||
{
|
||||
"type": "CWE",
|
||||
"lang": "en",
|
||||
"description": "CWE-400 Uncontrolled Resource Consumption",
|
||||
"cweId": "CWE-400"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"descriptions": [
|
||||
{
|
||||
"type": "CWE",
|
||||
"lang": "en",
|
||||
"description": "CWE-20 Improper Input Validation",
|
||||
"cweId": "CWE-20"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"x_generator": {
|
||||
"engine": "Vulnogram 0.0.9"
|
||||
},
|
||||
"source": {
|
||||
"discovery": "UNKNOWN"
|
||||
}
|
||||
},
|
||||
"adp": [
|
||||
{
|
||||
"providerMetadata": {
|
||||
"orgId": "af854a3a-2127-422b-91ae-364da2661108",
|
||||
"shortName": "CVE",
|
||||
"dateUpdated": "2024-08-04T04:17:24.696Z"
|
||||
},
|
||||
"title": "CVE Program Container",
|
||||
"references": [
|
||||
{
|
||||
"url": "https://logging.apache.org/log4j/2.x/security.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "[oss-security] 20211210 CVE-2021-44228: Apache Log4j2 JNDI features do not protect against attacker controlled LDAP and other JNDI related endpoints",
|
||||
"tags": [
|
||||
"mailing-list",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "http://www.openwall.com/lists/oss-security/2021/12/10/1"
|
||||
},
|
||||
{
|
||||
"name": "[oss-security] 20211210 Re: CVE-2021-44228: Apache Log4j2 JNDI features do not protect against attacker controlled LDAP and other JNDI related endpoints",
|
||||
"tags": [
|
||||
"mailing-list",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "http://www.openwall.com/lists/oss-security/2021/12/10/2"
|
||||
},
|
||||
{
|
||||
"name": "20211210 Vulnerability in Apache Log4j Library Affecting Cisco Products: December 2021",
|
||||
"tags": [
|
||||
"vendor-advisory",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-apache-log4j-qRuKNEbd"
|
||||
},
|
||||
{
|
||||
"name": "[oss-security] 20211210 Re: CVE-2021-44228: Apache Log4j2 JNDI features do not protect against attacker controlled LDAP and other JNDI related endpoints",
|
||||
"tags": [
|
||||
"mailing-list",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "http://www.openwall.com/lists/oss-security/2021/12/10/3"
|
||||
},
|
||||
{
|
||||
"url": "https://security.netapp.com/advisory/ntap-20211210-0007/",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165225/Apache-Log4j2-2.14.1-Remote-Code-Execution.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "https://psirt.global.sonicwall.com/vuln-detail/SNWLID-2021-0032",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "https://www.oracle.com/security-alerts/alert-cve-2021-44228.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DSA-5020",
|
||||
"tags": [
|
||||
"vendor-advisory",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "https://www.debian.org/security/2021/dsa-5020"
|
||||
},
|
||||
{
|
||||
"name": "[debian-lts-announce] 20211212 [SECURITY] [DLA 2842-1] apache-log4j2 security update",
|
||||
"tags": [
|
||||
"mailing-list",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "https://lists.debian.org/debian-lts-announce/2021/12/msg00007.html"
|
||||
},
|
||||
{
|
||||
"name": "FEDORA-2021-f0f501d01f",
|
||||
"tags": [
|
||||
"vendor-advisory",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "https://lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/VU57UJDCFIASIO35GC55JMKSRXJMCDFM/"
|
||||
},
|
||||
{
|
||||
"name": "Microsoft’s Response to CVE-2021-44228 Apache Log4j 2",
|
||||
"tags": [
|
||||
"vendor-advisory",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "https://msrc-blog.microsoft.com/2021/12/11/microsofts-response-to-cve-2021-44228-apache-log4j2/"
|
||||
},
|
||||
{
|
||||
"name": "[oss-security] 20211213 Re: CVE-2021-4104: Deserialization of untrusted data in JMSAppender in Apache Log4j 1.2",
|
||||
"tags": [
|
||||
"mailing-list",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "http://www.openwall.com/lists/oss-security/2021/12/13/2"
|
||||
},
|
||||
{
|
||||
"name": "[oss-security] 20211213 CVE-2021-4104: Deserialization of untrusted data in JMSAppender in Apache Log4j 1.2",
|
||||
"tags": [
|
||||
"mailing-list",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "http://www.openwall.com/lists/oss-security/2021/12/13/1"
|
||||
},
|
||||
{
|
||||
"name": "[oss-security] 20211214 CVE-2021-45046: Apache Log4j2 Thread Context Message Pattern and Context Lookup Pattern vulnerable to a denial of service attack",
|
||||
"tags": [
|
||||
"mailing-list",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "http://www.openwall.com/lists/oss-security/2021/12/14/4"
|
||||
},
|
||||
{
|
||||
"name": "20211210 A Vulnerability in Apache Log4j Library Affecting Cisco Products: December 2021",
|
||||
"tags": [
|
||||
"vendor-advisory",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-apache-log4j-qRuKNEbd"
|
||||
},
|
||||
{
|
||||
"name": "VU#930724",
|
||||
"tags": [
|
||||
"third-party-advisory",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "https://www.kb.cert.org/vuls/id/930724"
|
||||
},
|
||||
{
|
||||
"url": "https://twitter.com/kurtseifried/status/1469345530182455296",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "https://cert-portal.siemens.com/productcert/pdf/ssa-661247.pdf",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165260/VMware-Security-Advisory-2021-0028.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165270/Apache-Log4j2-2.14.1-Remote-Code-Execution.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165261/Apache-Log4j2-2.14.1-Information-Disclosure.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00646.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "20211210 Vulnerabilities in Apache Log4j Library Affecting Cisco Products: December 2021",
|
||||
"tags": [
|
||||
"vendor-advisory",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-apache-log4j-qRuKNEbd"
|
||||
},
|
||||
{
|
||||
"name": "[oss-security] 20211215 Re: CVE-2021-45046: Apache Log4j2 Thread Context Message Pattern and Context Lookup Pattern vulnerable to a denial of service attack",
|
||||
"tags": [
|
||||
"mailing-list",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "http://www.openwall.com/lists/oss-security/2021/12/15/3"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165282/Log4j-Payload-Generator.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165281/Log4j2-Log4Shell-Regexes.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165307/Log4j-Remote-Code-Execution-Word-Bypassing.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165311/log4j-scan-Extensive-Scanner.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165306/L4sh-Log4j-Remote-Code-Execution.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "https://cert-portal.siemens.com/productcert/pdf/ssa-714170.pdf",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "FEDORA-2021-66d6c484f3",
|
||||
"tags": [
|
||||
"vendor-advisory",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "https://lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/M5CSVUNV4HWZZXGOKNSK6L7RPM7BOKIB/"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165371/VMware-Security-Advisory-2021-0028.4.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "https://cert-portal.siemens.com/productcert/pdf/ssa-397453.pdf",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "https://cert-portal.siemens.com/productcert/pdf/ssa-479842.pdf",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "https://www.oracle.com/security-alerts/cpujan2022.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165532/Log4Shell-HTTP-Header-Injection.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/cisagov/log4j-affected-db/blob/develop/SOFTWARE-LIST.md",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165642/VMware-vCenter-Server-Unauthenticated-Log4Shell-JNDI-Injection-Remote-Code-Execution.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/165673/UniFi-Network-Application-Unauthenticated-Log4Shell-Remote-Code-Execution.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "20220314 APPLE-SA-2022-03-14-7 Xcode 13.3",
|
||||
"tags": [
|
||||
"mailing-list",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "http://seclists.org/fulldisclosure/2022/Mar/23"
|
||||
},
|
||||
{
|
||||
"url": "https://www.bentley.com/en/common-vulnerability-exposure/be-2022-0001",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/cisagov/log4j-affected-db",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "https://support.apple.com/kb/HT213189",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "https://www.oracle.com/security-alerts/cpuapr2022.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nu11secur1ty/CVE-mitre/tree/main/CVE-2021-44228",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "https://www.nu11secur1ty.com/2021/12/cve-2021-44228.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "20220721 Open-Xchange Security Advisory 2022-07-21",
|
||||
"tags": [
|
||||
"mailing-list",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "http://seclists.org/fulldisclosure/2022/Jul/11"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/167794/Open-Xchange-App-Suite-7.10.x-Cross-Site-Scripting-Command-Injection.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/167917/MobileIron-Log4Shell-Remote-Command-Execution.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "20221208 Intel Data Center Manager <= 5.1 Local Privileges Escalation",
|
||||
"tags": [
|
||||
"mailing-list",
|
||||
"x_transferred"
|
||||
],
|
||||
"url": "http://seclists.org/fulldisclosure/2022/Dec/2"
|
||||
},
|
||||
{
|
||||
"url": "http://packetstormsecurity.com/files/171626/AD-Manager-Plus-7122-Remote-Code-Execution.html",
|
||||
"tags": [
|
||||
"x_transferred"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"metrics": [
|
||||
{
|
||||
"cvssV3_1": {
|
||||
"scope": "CHANGED",
|
||||
"version": "3.1",
|
||||
"baseScore": 10,
|
||||
"attackVector": "NETWORK",
|
||||
"baseSeverity": "CRITICAL",
|
||||
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H",
|
||||
"integrityImpact": "HIGH",
|
||||
"userInteraction": "NONE",
|
||||
"attackComplexity": "LOW",
|
||||
"availabilityImpact": "HIGH",
|
||||
"privilegesRequired": "NONE",
|
||||
"confidentialityImpact": "HIGH"
|
||||
}
|
||||
},
|
||||
{
|
||||
"other": {
|
||||
"type": "ssvc",
|
||||
"content": {
|
||||
"id": "CVE-2021-44228",
|
||||
"role": "CISA Coordinator",
|
||||
"options": [
|
||||
{
|
||||
"Exploitation": "active"
|
||||
},
|
||||
{
|
||||
"Automatable": "yes"
|
||||
},
|
||||
{
|
||||
"Technical Impact": "total"
|
||||
}
|
||||
],
|
||||
"version": "2.0.3",
|
||||
"timestamp": "2025-02-04T14:25:34.416117Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"other": {
|
||||
"type": "kev",
|
||||
"content": {
|
||||
"dateAdded": "2021-12-10",
|
||||
"reference": "https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2021-44228"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"url": "https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2021-44228",
|
||||
"tags": [
|
||||
"government-resource"
|
||||
]
|
||||
}
|
||||
],
|
||||
"timeline": [
|
||||
{
|
||||
"time": "2021-12-10T00:00:00.000Z",
|
||||
"lang": "en",
|
||||
"value": "CVE-2021-44228 added to CISA KEV"
|
||||
}
|
||||
],
|
||||
"title": "CISA ADP Vulnrichment",
|
||||
"providerMetadata": {
|
||||
"orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
|
||||
"shortName": "CISA-ADP",
|
||||
"dateUpdated": "2025-10-21T23:25:23.121Z"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue