|
| 1 | +package main |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + "log/slog" |
| 6 | +) |
| 7 | + |
| 8 | +func main() {} |
| 9 | + |
| 10 | +func getUntrustedData() interface{} { return nil } |
| 11 | + |
| 12 | +func getUntrustedString() string { |
| 13 | + return "tainted string" |
| 14 | +} |
| 15 | + |
| 16 | +// Package-level convenience functions. |
| 17 | + |
| 18 | +func testSlogDebug() { |
| 19 | + slog.Debug(getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 20 | + slog.Debug("msg", "key", getUntrustedData()) // $ hasValueFlow="call to getUntrustedData" |
| 21 | + slog.Debug("msg", slog.String("key", getUntrustedString())) // $ hasTaintFlow="call to String" |
| 22 | +} |
| 23 | + |
| 24 | +func testSlogInfo() { |
| 25 | + slog.Info(getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 26 | + slog.Info("msg", slog.Any("key", getUntrustedData())) // $ hasTaintFlow="call to Any" |
| 27 | + slog.Info("msg", slog.String("key", getUntrustedString())) // $ hasTaintFlow="call to String" |
| 28 | +} |
| 29 | + |
| 30 | +func testSlogWarn() { |
| 31 | + slog.Warn(getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 32 | + slog.Warn("msg", slog.String("key", getUntrustedString())) // $ hasTaintFlow="call to String" |
| 33 | +} |
| 34 | + |
| 35 | +func testSlogError() { |
| 36 | + slog.Error(getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 37 | + slog.Error("msg", slog.String("key", getUntrustedString())) // $ hasTaintFlow="call to String" |
| 38 | +} |
| 39 | + |
| 40 | +func testSlogContextVariants(ctx context.Context) { |
| 41 | + slog.DebugContext(ctx, getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 42 | + slog.InfoContext(ctx, getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 43 | + slog.WarnContext(ctx, getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 44 | + slog.ErrorContext(ctx, getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 45 | + slog.InfoContext(ctx, "msg", slog.String("key", getUntrustedString())) // $ hasTaintFlow="call to String" |
| 46 | +} |
| 47 | + |
| 48 | +func testSlogLog(ctx context.Context) { |
| 49 | + slog.Log(ctx, slog.LevelInfo, getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 50 | + slog.Log(ctx, slog.LevelInfo, "msg", slog.String("key", getUntrustedString())) // $ hasTaintFlow="call to String" |
| 51 | + slog.LogAttrs(ctx, slog.LevelInfo, getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 52 | + slog.LogAttrs(ctx, slog.LevelInfo, "msg", slog.String("key", getUntrustedString())) // $ hasTaintFlow="call to String" |
| 53 | +} |
| 54 | + |
| 55 | +// Methods on *slog.Logger. |
| 56 | + |
| 57 | +func testLoggerMethods(logger *slog.Logger, ctx context.Context) { |
| 58 | + logger.Debug(getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 59 | + logger.Info(getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 60 | + logger.Warn(getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 61 | + logger.Error(getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 62 | + logger.Info("msg", slog.Any("key", getUntrustedData())) // $ hasTaintFlow="call to Any" |
| 63 | + logger.InfoContext(ctx, getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 64 | + logger.Log(ctx, slog.LevelInfo, getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 65 | + logger.LogAttrs(ctx, slog.LevelInfo, "msg", slog.String("key", getUntrustedString())) // $ hasTaintFlow="call to String" |
| 66 | +} |
| 67 | + |
| 68 | +// With, Logger.With and Logger.WithGroup. Note that for ease of modeling we make these functions |
| 69 | +// sinks, although strictly speaking we should consider logging functions called on the returned |
| 70 | +// loggers as the sinks. |
| 71 | + |
| 72 | +func testWith(logger *slog.Logger) { |
| 73 | + logger1 := logger.With(slog.String("key", getUntrustedString())) // $ hasTaintFlow="call to String" |
| 74 | + logger1.Info("hello world") |
| 75 | + logger2 := logger.With(slog.Any(getUntrustedString(), nil)) // $ hasTaintFlow="call to Any" |
| 76 | + logger2.Info("hello world") |
| 77 | + logger.With("key", getUntrustedData()).Info("hello world") // $ hasValueFlow="call to getUntrustedData" |
| 78 | +} |
| 79 | + |
| 80 | +func testPackageWith() { |
| 81 | + logger := slog.With(slog.String("key", getUntrustedString())) // $ hasTaintFlow="call to String" |
| 82 | + logger.Info("hello world") |
| 83 | + slog.With("key", getUntrustedData()).Info("hello world") // $ hasValueFlow="call to getUntrustedData" |
| 84 | +} |
| 85 | + |
| 86 | +func testWithGroup(logger *slog.Logger) { |
| 87 | + grouped := logger.WithGroup(getUntrustedString()) // $ hasValueFlow="call to getUntrustedString" |
| 88 | + grouped.Info("hello world") |
| 89 | +} |
| 90 | + |
| 91 | +// Summary models: functions relating to Attr/Value that propagate strings. |
| 92 | + |
| 93 | +func testAttrConstructors(logger *slog.Logger) { |
| 94 | + logger.Info("msg", slog.Group("group", slog.String("key", getUntrustedString()))) // $ hasTaintFlow="call to Group" |
| 95 | + logger.Info("msg", slog.GroupAttrs("group", slog.String("key", getUntrustedString()))) // $ hasTaintFlow="call to GroupAttrs" |
| 96 | +} |
| 97 | + |
| 98 | +func testValueConstructors(logger *slog.Logger) { |
| 99 | + logger.Info("msg", "key", slog.AnyValue(getUntrustedString())) // $ hasTaintFlow="call to AnyValue" |
| 100 | + logger.Info("msg", "key", slog.StringValue(getUntrustedString())) // $ hasTaintFlow="call to StringValue" |
| 101 | + attr := slog.String("key", getUntrustedString()) |
| 102 | + logger.Info("msg", "key", slog.GroupValue(attr)) // $ hasTaintFlow="call to GroupValue" |
| 103 | +} |
| 104 | + |
| 105 | +func testAttrAndValueAccessors(logger *slog.Logger) { |
| 106 | + attr := slog.String("key", getUntrustedString()) |
| 107 | + logger.Info("msg", "key", attr.String()) // $ hasTaintFlow="call to String" |
| 108 | + |
| 109 | + v := slog.AnyValue(getUntrustedString()) |
| 110 | + logger.Info("msg", "key", v.Any()) // $ hasTaintFlow="call to Any" |
| 111 | + logger.Info("msg", "key", v.String()) // $ hasTaintFlow="call to String" |
| 112 | + |
| 113 | + group := slog.GroupValue(slog.String("key", getUntrustedString())) |
| 114 | + logger.Info("msg", group.Group()[0]) // $ hasTaintFlow="index expression" |
| 115 | +} |
0 commit comments