From 4c411bbcb5de03da4d852d742aa1da6777b095c8 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 10 Jun 2026 07:07:49 +0200 Subject: [PATCH 1/3] Convert hand-rolled inline expectations test --- .../go/frameworks/Twirp/RequestForgery.qlref | 4 +- .../semmle/go/frameworks/Twirp/client/main.go | 2 +- .../frameworks/Twirp/rpc/notes/service.pb.go | 10 +- .../Twirp/rpc/notes/service.twirp.go | 36 +-- .../semmle/go/frameworks/Twirp/server/main.go | 10 +- .../semmle/go/frameworks/Twirp/tests.expected | 32 +-- .../semmle/go/frameworks/Twirp/tests.ql | 229 +++++------------- 7 files changed, 95 insertions(+), 228 deletions(-) diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/RequestForgery.qlref b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/RequestForgery.qlref index 061679da228d..760862973f1d 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/RequestForgery.qlref +++ b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/RequestForgery.qlref @@ -1,2 +1,4 @@ query: Security/CWE-918/RequestForgery.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/client/main.go b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/client/main.go index 76abd1a0a9c2..e5b4cd2351dc 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/client/main.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/client/main.go @@ -9,7 +9,7 @@ import ( ) func main() { - client := notes.NewNotesServiceProtobufClient("http://localhost:8000", &http.Client{}) // test: ssrfSink + client := notes.NewNotesServiceProtobufClient("http://localhost:8000", &http.Client{}) // $ ssrfSink ctx := context.Background() diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/rpc/notes/service.pb.go b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/rpc/notes/service.pb.go index f0c3e4910d98..e91168f43a96 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/rpc/notes/service.pb.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/rpc/notes/service.pb.go @@ -20,7 +20,7 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -type Note struct { // test: message +type Note struct { // $ message state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -83,7 +83,7 @@ func (x *Note) GetCreatedAt() int64 { return 0 } -type CreateNoteParams struct { // test: message +type CreateNoteParams struct { // $ message state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -130,7 +130,7 @@ func (x *CreateNoteParams) GetText() string { return "" } -type GetAllNotesParams struct { // test: message +type GetAllNotesParams struct { // $ message state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -168,7 +168,7 @@ func (*GetAllNotesParams) Descriptor() ([]byte, []int) { return file_rpc_notes_service_proto_rawDescGZIP(), []int{2} } -type GetAllNotesResult struct { // test: message +type GetAllNotesResult struct { // $ message state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -340,7 +340,7 @@ func file_rpc_notes_service_proto_init() { } } } - type x struct{} + type x struct{} // $ SPURIOUS: message // not message out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/rpc/notes/service.twirp.go b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/rpc/notes/service.twirp.go index 19bcc56f2612..6b34dcf08ead 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/rpc/notes/service.twirp.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/rpc/notes/service.twirp.go @@ -31,7 +31,7 @@ const _ = twirp.TwirpPackageMinVersion_8_1_0 // NotesService Interface // ====================== -type NotesService interface { // test: serviceInterface +type NotesService interface { // $ serviceInterface CreateNote(context.Context, *CreateNoteParams) (*Note, error) GetAllNotes(context.Context, *GetAllNotesParams) (*GetAllNotesResult, error) @@ -41,7 +41,7 @@ type NotesService interface { // test: serviceInterface // NotesService Protobuf Client // ============================ -type notesServiceProtobufClient struct { // test: serviceClient +type notesServiceProtobufClient struct { // $ serviceClient client HTTPClient urls [2]string interceptor twirp.Interceptor @@ -50,7 +50,7 @@ type notesServiceProtobufClient struct { // test: serviceClient // NewNotesServiceProtobufClient creates a Protobuf client that implements the NotesService interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. -func NewNotesServiceProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) NotesService { // test: clientConstructor +func NewNotesServiceProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) NotesService { // $ clientConstructor if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } @@ -84,7 +84,7 @@ func NewNotesServiceProtobufClient(baseURL string, client HTTPClient, opts ...tw } } -func (c *notesServiceProtobufClient) CreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // test: !handler +func (c *notesServiceProtobufClient) CreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // not handler ctx = ctxsetters.WithPackageName(ctx, "gotwirprpcexample.rpc.notes") ctx = ctxsetters.WithServiceName(ctx, "NotesService") ctx = ctxsetters.WithMethodName(ctx, "CreateNote") @@ -113,7 +113,7 @@ func (c *notesServiceProtobufClient) CreateNote(ctx context.Context, in *CreateN return caller(ctx, in) } -func (c *notesServiceProtobufClient) callCreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // test: !handler +func (c *notesServiceProtobufClient) callCreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // not handler out := new(Note) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { @@ -130,7 +130,7 @@ func (c *notesServiceProtobufClient) callCreateNote(ctx context.Context, in *Cre return out, nil } -func (c *notesServiceProtobufClient) GetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // test: !handler +func (c *notesServiceProtobufClient) GetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // not handler ctx = ctxsetters.WithPackageName(ctx, "gotwirprpcexample.rpc.notes") ctx = ctxsetters.WithServiceName(ctx, "NotesService") ctx = ctxsetters.WithMethodName(ctx, "GetAllNotes") @@ -159,7 +159,7 @@ func (c *notesServiceProtobufClient) GetAllNotes(ctx context.Context, in *GetAll return caller(ctx, in) } -func (c *notesServiceProtobufClient) callGetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // test: !handler +func (c *notesServiceProtobufClient) callGetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // not handler out := new(GetAllNotesResult) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out) if err != nil { @@ -180,7 +180,7 @@ func (c *notesServiceProtobufClient) callGetAllNotes(ctx context.Context, in *Ge // NotesService JSON Client // ======================== -type notesServiceJSONClient struct { // test: serviceClient +type notesServiceJSONClient struct { // $ serviceClient client HTTPClient urls [2]string interceptor twirp.Interceptor @@ -189,7 +189,7 @@ type notesServiceJSONClient struct { // test: serviceClient // NewNotesServiceJSONClient creates a JSON client that implements the NotesService interface. // It communicates using JSON and can be configured with a custom HTTPClient. -func NewNotesServiceJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) NotesService { // test: clientConstructor +func NewNotesServiceJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) NotesService { // $ clientConstructor if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } @@ -223,7 +223,7 @@ func NewNotesServiceJSONClient(baseURL string, client HTTPClient, opts ...twirp. } } -func (c *notesServiceJSONClient) CreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // test: !handler +func (c *notesServiceJSONClient) CreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // not handler ctx = ctxsetters.WithPackageName(ctx, "gotwirprpcexample.rpc.notes") ctx = ctxsetters.WithServiceName(ctx, "NotesService") ctx = ctxsetters.WithMethodName(ctx, "CreateNote") @@ -252,7 +252,7 @@ func (c *notesServiceJSONClient) CreateNote(ctx context.Context, in *CreateNoteP return caller(ctx, in) } -func (c *notesServiceJSONClient) callCreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // test: !handler +func (c *notesServiceJSONClient) callCreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // not handler out := new(Note) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { @@ -269,7 +269,7 @@ func (c *notesServiceJSONClient) callCreateNote(ctx context.Context, in *CreateN return out, nil } -func (c *notesServiceJSONClient) GetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // test: !handler +func (c *notesServiceJSONClient) GetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // not handler ctx = ctxsetters.WithPackageName(ctx, "gotwirprpcexample.rpc.notes") ctx = ctxsetters.WithServiceName(ctx, "NotesService") ctx = ctxsetters.WithMethodName(ctx, "GetAllNotes") @@ -298,7 +298,7 @@ func (c *notesServiceJSONClient) GetAllNotes(ctx context.Context, in *GetAllNote return caller(ctx, in) } -func (c *notesServiceJSONClient) callGetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // test: !handler +func (c *notesServiceJSONClient) callGetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // not handler out := new(GetAllNotesResult) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out) if err != nil { @@ -319,7 +319,7 @@ func (c *notesServiceJSONClient) callGetAllNotes(ctx context.Context, in *GetAll // NotesService Server Handler // =========================== -type notesServiceServer struct { // test: serviceServer +type notesServiceServer struct { // $ serviceServer NotesService interceptor twirp.Interceptor hooks *twirp.ServerHooks @@ -331,7 +331,7 @@ type notesServiceServer struct { // test: serviceServer // NewNotesServiceServer builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). -func NewNotesServiceServer(svc NotesService, opts ...interface{}) TwirpServer { // test: serverConstructor +func NewNotesServiceServer(svc NotesService, opts ...interface{}) TwirpServer { // $ serverConstructor serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future @@ -535,7 +535,7 @@ func (s *notesServiceServer) serveCreateNoteProtobuf(ctx context.Context, resp h return } - buf, err := io.ReadAll(req.Body) + buf, err := io.ReadAll(req.Body) // $ Source if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return @@ -812,7 +812,7 @@ func (s *notesServiceServer) PathPrefix() string { // automatically disabled if *(net/http).Client is passed to client // constructors. See the withoutRedirects function in this file for more // details. -type HTTPClient interface { +type HTTPClient interface { // $ SPURIOUS: serviceInterface // not serviceInterface Do(req *http.Request) (*http.Response, error) } @@ -820,7 +820,7 @@ type HTTPClient interface { // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. // Most people can think of TwirpServers as just http.Handlers. -type TwirpServer interface { +type TwirpServer interface { // $ SPURIOUS: serviceInterface // not serviceInterface http.Handler // ServiceDescriptor returns gzipped bytes describing the .proto file that diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/server/main.go b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/server/main.go index 203b3af17361..7499e79f827f 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/server/main.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/server/main.go @@ -16,7 +16,7 @@ type notesService struct { CurrentId int32 } -func (s *notesService) CreateNote(ctx context.Context, params *notes.CreateNoteParams) (*notes.Note, error) { // test: routeHandler, request +func (s *notesService) CreateNote(ctx context.Context, params *notes.CreateNoteParams) (*notes.Note, error) { // $ Source request handler // route handler if len(params.Text) < 4 { return nil, twirp.InvalidArgument.Error("Text should be min 4 characters.") } @@ -27,8 +27,8 @@ func (s *notesService) CreateNote(ctx context.Context, params *notes.CreateNoteP CreatedAt: time.Now().UnixMilli(), } - notes.NewNotesServiceProtobufClient(params.Text, &http.Client{}) // test: ssrfSink, ssrf - notes.NewNotesServiceProtobufClient(strconv.FormatInt(int64(s.CurrentId), 10), &http.Client{}) // test: ssrfSink, !ssrf + notes.NewNotesServiceProtobufClient(params.Text, &http.Client{}) // $ Alert ssrfSink ssrf + notes.NewNotesServiceProtobufClient(strconv.FormatInt(int64(s.CurrentId), 10), &http.Client{}) // $ ssrfSink // not ssrf s.Notes = append(s.Notes, note) @@ -37,7 +37,7 @@ func (s *notesService) CreateNote(ctx context.Context, params *notes.CreateNoteP return ¬e, nil } -func (s *notesService) GetAllNotes(ctx context.Context, params *notes.GetAllNotesParams) (*notes.GetAllNotesResult, error) { // test: routeHandler, request +func (s *notesService) GetAllNotes(ctx context.Context, params *notes.GetAllNotesParams) (*notes.GetAllNotesResult, error) { // $ request handler // route handler allNotes := make([]*notes.Note, 0) fmt.Println(params) @@ -57,7 +57,7 @@ func main() { mux := http.NewServeMux() mux.Handle(notesServer.PathPrefix(), notesServer) - err := http.ListenAndServe(":8000", notesServer) // test: !ssrfSink + err := http.ListenAndServe(":8000", notesServer) // not ssrfSink if err != nil { panic(err) } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/tests.expected b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/tests.expected index 4b0a2d917e71..42831abaf155 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/tests.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/tests.expected @@ -1,32 +1,2 @@ invalidModelRow -passingPositiveTests -| PASSED | clientConstructor | rpc/notes/service.twirp.go:53:114:53:139 | comment | -| PASSED | clientConstructor | rpc/notes/service.twirp.go:192:110:192:135 | comment | -| PASSED | message | rpc/notes/service.pb.go:23:20:23:35 | comment | -| PASSED | message | rpc/notes/service.pb.go:86:32:86:47 | comment | -| PASSED | message | rpc/notes/service.pb.go:133:33:133:48 | comment | -| PASSED | message | rpc/notes/service.pb.go:171:33:171:48 | comment | -| PASSED | request | server/main.go:19:111:19:140 | comment | -| PASSED | request | server/main.go:40:126:40:155 | comment | -| PASSED | serverConstructor | rpc/notes/service.twirp.go:334:81:334:106 | comment | -| PASSED | serviceClient | rpc/notes/service.twirp.go:44:42:44:63 | comment | -| PASSED | serviceClient | rpc/notes/service.twirp.go:183:38:183:59 | comment | -| PASSED | serviceInterface | rpc/notes/service.twirp.go:34:31:34:55 | comment | -| PASSED | serviceServer | rpc/notes/service.twirp.go:322:34:322:55 | comment | -| PASSED | ssrf | server/main.go:30:97:30:119 | comment | -| PASSED | ssrfSink | client/main.go:12:89:12:105 | comment | -| PASSED | ssrfSink | server/main.go:30:97:30:119 | comment | -| PASSED | ssrfSink | server/main.go:31:97:31:120 | comment | -failingPositiveTests -passingNegativeTests -| PASSED | !handler | rpc/notes/service.twirp.go:87:109:87:125 | comment | -| PASSED | !handler | rpc/notes/service.twirp.go:116:113:116:129 | comment | -| PASSED | !handler | rpc/notes/service.twirp.go:133:124:133:140 | comment | -| PASSED | !handler | rpc/notes/service.twirp.go:162:128:162:144 | comment | -| PASSED | !handler | rpc/notes/service.twirp.go:226:105:226:121 | comment | -| PASSED | !handler | rpc/notes/service.twirp.go:255:109:255:125 | comment | -| PASSED | !handler | rpc/notes/service.twirp.go:272:120:272:136 | comment | -| PASSED | !handler | rpc/notes/service.twirp.go:301:124:301:140 | comment | -| PASSED | !ssrf | server/main.go:31:97:31:120 | comment | -| PASSED | !ssrfSink | server/main.go:60:51:60:68 | comment | -failingNegativeTests +testFailures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/tests.ql b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/tests.ql index 5866b6ff3eda..2b445ce4d86b 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/tests.ql +++ b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/tests.ql @@ -2,181 +2,76 @@ import go import semmle.go.dataflow.ExternalFlow import ModelValidation import semmle.go.security.RequestForgery +import utils.test.InlineExpectationsTest -class InlineTest extends LineComment { - string tests; - - InlineTest() { tests = this.getText().regexpCapture("\\s*test:(.*)", 1) } - - string getPositiveTest() { - result = tests.trim().splitAt(",").trim() and not result.matches("!%") +module TwirpTest implements TestSig { + string getARelevantTag() { + result = + [ + "handler", "request", "ssrfSink", "message", "serviceInterface", "serviceClient", + "serviceServer", "clientConstructor", "serverConstructor", "ssrf" + ] } - string getNegativeTest() { result = tests.trim().splitAt(",").trim() and result.matches("!%") } - - predicate hasPositiveTest(string test) { test = this.getPositiveTest() } - - predicate hasNegativeTest(string test) { test = this.getNegativeTest() } - - predicate inNode(DataFlow::Node n) { - this.getLocation().getFile() = n.getFile() and - this.getLocation().getStartLine() = n.getStartLine() + additional predicate hasEntityResult(Location location, string element, Entity entity) { + location = entity.getDeclaration().getLocation() and + element = entity.toString() } - predicate inEntity(Entity e) { - this.getLocation().getFile() = e.getDeclaration().getFile() and - this.getLocation().getStartLine() = e.getDeclaration().getLocation().getStartLine() + additional predicate hasTypeResult(Location location, string element, Type goType) { + exists(TypeEntity typeEntity | + typeEntity.getType() = goType and + location = typeEntity.getDeclaration().getLocation() and + element = goType.toString() + ) } - predicate inType(Type t) { - exists(TypeEntity te | - te.getType() = t and - this.getLocation().getFile() = te.getDeclaration().getFile() and - this.getLocation().getStartLine() = te.getDeclaration().getLocation().getStartLine() + predicate hasActualResult(Location location, string element, string tag, string value) { + value = "" and + ( + tag = "handler" and + exists(Twirp::ServiceHandler handler | hasEntityResult(location, element, handler)) + or + tag = "request" and + exists(Twirp::Request request | + location = request.getLocation() and + element = request.toString() + ) + or + tag = "ssrfSink" and + exists(RequestForgery::Sink sink | + location = sink.getLocation() and + element = sink.toString() + ) + or + tag = "message" and + exists(Twirp::ProtobufMessageType message | hasTypeResult(location, element, message)) + or + tag = "serviceInterface" and + exists(Twirp::ServiceInterfaceType serviceInterface | + hasTypeResult(location, element, serviceInterface.getDefinedType()) + ) + or + tag = "serviceClient" and + exists(Twirp::ServiceClientType client | hasTypeResult(location, element, client)) + or + tag = "serviceServer" and + exists(Twirp::ServiceServerType server | hasTypeResult(location, element, server)) + or + tag = "clientConstructor" and + exists(Twirp::ClientConstructor constructor | hasEntityResult(location, element, constructor)) + or + tag = "serverConstructor" and + exists(Twirp::ServerConstructor constructor | hasEntityResult(location, element, constructor)) + or + tag = "ssrf" and + exists(DataFlow::Node sink | + RequestForgery::Flow::flowTo(sink) and + location = sink.getLocation() and + element = sink.toString() + ) ) } } -query predicate passingPositiveTests(string res, string expectation, InlineTest t) { - res = "PASSED" and - t.hasPositiveTest(expectation) and - ( - expectation = "handler" and - exists(Twirp::ServiceHandler n | t.inEntity(n)) - or - expectation = "request" and - exists(Twirp::Request n | t.inNode(n)) - or - expectation = "ssrfSink" and - exists(RequestForgery::Sink n | t.inNode(n)) - or - expectation = "message" and - exists(Twirp::ProtobufMessageType n | t.inType(n)) - or - expectation = "serviceInterface" and - exists(Twirp::ServiceInterfaceType n | t.inType(n.getDefinedType())) - or - expectation = "serviceClient" and - exists(Twirp::ServiceClientType n | t.inType(n)) - or - expectation = "serviceServer" and - exists(Twirp::ServiceServerType n | t.inType(n)) - or - expectation = "clientConstructor" and - exists(Twirp::ClientConstructor n | t.inEntity(n)) - or - expectation = "serverConstructor" and - exists(Twirp::ServerConstructor n | t.inEntity(n)) - or - expectation = "ssrf" and - exists(DataFlow::Node sink | RequestForgery::Flow::flowTo(sink) and t.inNode(sink)) - ) -} - -query predicate failingPositiveTests(string res, string expectation, InlineTest t) { - res = "FAILED" and - t.hasPositiveTest(expectation) and - ( - expectation = "handler" and - not exists(Twirp::ServiceHandler n | t.inEntity(n)) - or - expectation = "request" and - not exists(Twirp::Request n | t.inNode(n)) - or - expectation = "ssrfSink" and - not exists(RequestForgery::Sink n | t.inNode(n)) - or - expectation = "message" and - not exists(Twirp::ProtobufMessageType n | t.inType(n)) - or - expectation = "serviceInterface" and - not exists(Twirp::ServiceInterfaceType n | t.inType(n.getDefinedType())) - or - expectation = "serviceClient" and - not exists(Twirp::ServiceClientType n | t.inType(n)) - or - expectation = "serviceServer" and - not exists(Twirp::ServiceServerType n | t.inType(n)) - or - expectation = "clientConstructor" and - not exists(Twirp::ClientConstructor n | t.inEntity(n)) - or - expectation = "serverConstructor" and - not exists(Twirp::ServerConstructor n | t.inEntity(n)) - or - expectation = "ssrf" and - not exists(DataFlow::Node sink | RequestForgery::Flow::flowTo(sink) and t.inNode(sink)) - ) -} - -query predicate passingNegativeTests(string res, string expectation, InlineTest t) { - res = "PASSED" and - t.hasNegativeTest(expectation) and - ( - expectation = "!handler" and - not exists(Twirp::ServiceHandler n | t.inEntity(n)) - or - expectation = "!request" and - not exists(Twirp::Request n | t.inNode(n)) - or - expectation = "!ssrfSink" and - not exists(RequestForgery::Sink n | t.inNode(n)) - or - expectation = "!message" and - not exists(Twirp::ProtobufMessageType n | t.inType(n)) - or - expectation = "!serviceInterface" and - not exists(Twirp::ServiceInterfaceType n | t.inType(n)) - or - expectation = "!serviceClient" and - not exists(Twirp::ServiceClientType n | t.inType(n)) - or - expectation = "!serviceServer" and - not exists(Twirp::ServiceServerType n | t.inType(n)) - or - expectation = "!clientConstructor" and - not exists(Twirp::ClientConstructor n | t.inEntity(n)) - or - expectation = "!serverConstructor" and - not exists(Twirp::ServerConstructor n | t.inEntity(n)) - or - expectation = "!ssrf" and - not exists(DataFlow::Node sink | RequestForgery::Flow::flowTo(sink) and t.inNode(sink)) - ) -} - -query predicate failingNegativeTests(string res, string expectation, InlineTest t) { - res = "FAILED" and - t.hasNegativeTest(expectation) and - ( - expectation = "!handler" and - exists(Twirp::ServiceHandler n | t.inEntity(n)) - or - expectation = "!request" and - exists(Twirp::Request n | t.inNode(n)) - or - expectation = "!ssrfSink" and - exists(RequestForgery::Sink n | t.inNode(n)) - or - expectation = "!message" and - exists(Twirp::ProtobufMessageType n | t.inType(n)) - or - expectation = "!serviceInterface" and - exists(Twirp::ServiceInterfaceType n | t.inType(n)) - or - expectation = "!serviceClient" and - exists(Twirp::ServiceClientType n | t.inType(n)) - or - expectation = "!serviceServer" and - exists(Twirp::ServiceServerType n | t.inType(n)) - or - expectation = "!clientConstructor" and - exists(Twirp::ClientConstructor n | t.inEntity(n)) - or - expectation = "!serverConstructor" and - exists(Twirp::ServerConstructor n | t.inEntity(n)) - or - expectation = "!ssrf" and - exists(DataFlow::Node sink | RequestForgery::Flow::flowTo(sink) and t.inNode(sink)) - ) -} +import MakeTest From 6a8e20a0c87d3e8cc027db59db5afd985e48d74a Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 10 Jun 2026 07:12:08 +0200 Subject: [PATCH 2/3] Fix pre-existing whitespace issues in go test files --- .../WhitespaceContradictsPrecedence/main.go | 2 +- .../Security/CWE-089/StringBreak.expected | 40 +++++++++---------- .../Security/CWE-089/StringBreak.go | 1 + .../Security/CWE-089/StringBreakMismatched.go | 3 +- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/go/ql/test/query-tests/InconsistentCode/WhitespaceContradictsPrecedence/main.go b/go/ql/test/query-tests/InconsistentCode/WhitespaceContradictsPrecedence/main.go index faf23f9f1cfa..dc1bf222aec4 100644 --- a/go/ql/test/query-tests/InconsistentCode/WhitespaceContradictsPrecedence/main.go +++ b/go/ql/test/query-tests/InconsistentCode/WhitespaceContradictsPrecedence/main.go @@ -21,7 +21,7 @@ func ok3(x int) int { func ok4(x int, y int, z int) int { return x + y + z; } - + func ok5(x int, y int, z int) int { return x + y+z; } diff --git a/go/ql/test/query-tests/Security/CWE-089/StringBreak.expected b/go/ql/test/query-tests/Security/CWE-089/StringBreak.expected index 5deab249337e..63caa73d596d 100644 --- a/go/ql/test/query-tests/Security/CWE-089/StringBreak.expected +++ b/go/ql/test/query-tests/Security/CWE-089/StringBreak.expected @@ -1,26 +1,26 @@ #select -| StringBreak.go:14:47:14:57 | versionJSON | StringBreak.go:10:2:10:40 | ... := ...[0] | StringBreak.go:14:47:14:57 | versionJSON | If this $@ contains a single quote, it could break out of the enclosing quotes. | StringBreak.go:10:2:10:40 | ... := ...[0] | JSON value | -| StringBreakMismatched.go:17:26:17:32 | escaped | StringBreakMismatched.go:12:2:12:40 | ... := ...[0] | StringBreakMismatched.go:17:26:17:32 | escaped | If this $@ contains a single quote, it could break out of the enclosing quotes. | StringBreakMismatched.go:12:2:12:40 | ... := ...[0] | JSON value | -| StringBreakMismatched.go:29:27:29:33 | escaped | StringBreakMismatched.go:24:2:24:40 | ... := ...[0] | StringBreakMismatched.go:29:27:29:33 | escaped | If this $@ contains a double quote, it could break out of the enclosing quotes. | StringBreakMismatched.go:24:2:24:40 | ... := ...[0] | JSON value | +| StringBreak.go:15:47:15:57 | versionJSON | StringBreak.go:11:2:11:40 | ... := ...[0] | StringBreak.go:15:47:15:57 | versionJSON | If this $@ contains a single quote, it could break out of the enclosing quotes. | StringBreak.go:11:2:11:40 | ... := ...[0] | JSON value | +| StringBreakMismatched.go:18:26:18:32 | escaped | StringBreakMismatched.go:13:2:13:40 | ... := ...[0] | StringBreakMismatched.go:18:26:18:32 | escaped | If this $@ contains a single quote, it could break out of the enclosing quotes. | StringBreakMismatched.go:13:2:13:40 | ... := ...[0] | JSON value | +| StringBreakMismatched.go:30:27:30:33 | escaped | StringBreakMismatched.go:25:2:25:40 | ... := ...[0] | StringBreakMismatched.go:30:27:30:33 | escaped | If this $@ contains a double quote, it could break out of the enclosing quotes. | StringBreakMismatched.go:25:2:25:40 | ... := ...[0] | JSON value | edges -| StringBreak.go:10:2:10:40 | ... := ...[0] | StringBreak.go:14:47:14:57 | versionJSON | provenance | | -| StringBreakMismatched.go:12:2:12:40 | ... := ...[0] | StringBreakMismatched.go:13:29:13:47 | type conversion | provenance | | -| StringBreakMismatched.go:13:13:13:62 | call to Replace | StringBreakMismatched.go:17:26:17:32 | escaped | provenance | | -| StringBreakMismatched.go:13:29:13:47 | type conversion | StringBreakMismatched.go:13:13:13:62 | call to Replace | provenance | MaD:1 | -| StringBreakMismatched.go:24:2:24:40 | ... := ...[0] | StringBreakMismatched.go:25:29:25:47 | type conversion | provenance | | -| StringBreakMismatched.go:25:13:25:61 | call to Replace | StringBreakMismatched.go:29:27:29:33 | escaped | provenance | | -| StringBreakMismatched.go:25:29:25:47 | type conversion | StringBreakMismatched.go:25:13:25:61 | call to Replace | provenance | MaD:1 | +| StringBreak.go:11:2:11:40 | ... := ...[0] | StringBreak.go:15:47:15:57 | versionJSON | provenance | | +| StringBreakMismatched.go:13:2:13:40 | ... := ...[0] | StringBreakMismatched.go:14:29:14:47 | type conversion | provenance | | +| StringBreakMismatched.go:14:13:14:62 | call to Replace | StringBreakMismatched.go:18:26:18:32 | escaped | provenance | | +| StringBreakMismatched.go:14:29:14:47 | type conversion | StringBreakMismatched.go:14:13:14:62 | call to Replace | provenance | MaD:1 | +| StringBreakMismatched.go:25:2:25:40 | ... := ...[0] | StringBreakMismatched.go:26:29:26:47 | type conversion | provenance | | +| StringBreakMismatched.go:26:13:26:61 | call to Replace | StringBreakMismatched.go:30:27:30:33 | escaped | provenance | | +| StringBreakMismatched.go:26:29:26:47 | type conversion | StringBreakMismatched.go:26:13:26:61 | call to Replace | provenance | MaD:1 | models | 1 | Summary: strings; ; false; Replace; ; ; Argument[0]; ReturnValue; taint; manual | nodes -| StringBreak.go:10:2:10:40 | ... := ...[0] | semmle.label | ... := ...[0] | -| StringBreak.go:14:47:14:57 | versionJSON | semmle.label | versionJSON | -| StringBreakMismatched.go:12:2:12:40 | ... := ...[0] | semmle.label | ... := ...[0] | -| StringBreakMismatched.go:13:13:13:62 | call to Replace | semmle.label | call to Replace | -| StringBreakMismatched.go:13:29:13:47 | type conversion | semmle.label | type conversion | -| StringBreakMismatched.go:17:26:17:32 | escaped | semmle.label | escaped | -| StringBreakMismatched.go:24:2:24:40 | ... := ...[0] | semmle.label | ... := ...[0] | -| StringBreakMismatched.go:25:13:25:61 | call to Replace | semmle.label | call to Replace | -| StringBreakMismatched.go:25:29:25:47 | type conversion | semmle.label | type conversion | -| StringBreakMismatched.go:29:27:29:33 | escaped | semmle.label | escaped | +| StringBreak.go:11:2:11:40 | ... := ...[0] | semmle.label | ... := ...[0] | +| StringBreak.go:15:47:15:57 | versionJSON | semmle.label | versionJSON | +| StringBreakMismatched.go:13:2:13:40 | ... := ...[0] | semmle.label | ... := ...[0] | +| StringBreakMismatched.go:14:13:14:62 | call to Replace | semmle.label | call to Replace | +| StringBreakMismatched.go:14:29:14:47 | type conversion | semmle.label | type conversion | +| StringBreakMismatched.go:18:26:18:32 | escaped | semmle.label | escaped | +| StringBreakMismatched.go:25:2:25:40 | ... := ...[0] | semmle.label | ... := ...[0] | +| StringBreakMismatched.go:26:13:26:61 | call to Replace | semmle.label | call to Replace | +| StringBreakMismatched.go:26:29:26:47 | type conversion | semmle.label | type conversion | +| StringBreakMismatched.go:30:27:30:33 | escaped | semmle.label | escaped | subpaths diff --git a/go/ql/test/query-tests/Security/CWE-089/StringBreak.go b/go/ql/test/query-tests/Security/CWE-089/StringBreak.go index d5aec9777d42..5667ca350356 100644 --- a/go/ql/test/query-tests/Security/CWE-089/StringBreak.go +++ b/go/ql/test/query-tests/Security/CWE-089/StringBreak.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "fmt" + sq "github.com/Masterminds/squirrel" ) diff --git a/go/ql/test/query-tests/Security/CWE-089/StringBreakMismatched.go b/go/ql/test/query-tests/Security/CWE-089/StringBreakMismatched.go index ba8ee72d0fa8..c838d5f6b7da 100644 --- a/go/ql/test/query-tests/Security/CWE-089/StringBreakMismatched.go +++ b/go/ql/test/query-tests/Security/CWE-089/StringBreakMismatched.go @@ -2,8 +2,9 @@ package main import ( "encoding/json" - sq "github.com/Masterminds/squirrel" "strings" + + sq "github.com/Masterminds/squirrel" ) // Bad because quote characters are removed before concatenation, From b4a9689341383f94ec8979d381e59ec7d460e849 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 10 Jun 2026 06:43:10 +0200 Subject: [PATCH 3/3] Convert .qlref test to inline expectations --- .../experimental/CWE-525/WebCacheDeception.ql | 2 +- .../experimental/CWE-090/LDAPInjection.go | 24 +-- .../experimental/CWE-090/LDAPInjection.qlref | 4 +- go/ql/test/experimental/CWE-203/Timing.qlref | 4 +- go/ql/test/experimental/CWE-203/timing.go | 12 +- .../experimental/CWE-285/PamAuthBypass.qlref | 3 +- go/ql/test/experimental/CWE-285/main.go | 2 +- .../experimental/CWE-287/ImproperLdapAuth.go | 8 +- .../CWE-287/ImproperLdapAuth.qlref | 4 +- .../CWE-321-V2/HardCodedKeys.expected | 6 +- .../CWE-321-V2/HardCodedKeys.qlref | 3 +- .../experimental/CWE-321-V2/go-jose.v3.go | 4 +- .../experimental/CWE-321-V2/golang-jwt-v5.go | 4 +- .../test/experimental/CWE-369/DivideByZero.go | 24 +-- .../experimental/CWE-369/DivideByZero.qlref | 4 +- .../CWE-400/DatabaseCallInLoop.expected | 8 +- .../CWE-400/DatabaseCallInLoop.go | 4 +- .../CWE-400/DatabaseCallInLoop.qlref | 3 +- go/ql/test/experimental/CWE-400/test.go | 6 +- .../DecompressionBombs.qlref | 4 +- .../CWE-522-DecompressionBombs/test.go | 104 +++++------ .../CWE-525/WebCacheDeception.qlref | 3 +- .../CWE-525/WebCacheDeceptionBad.go | 2 +- .../CWE-525/WebCacheDeceptionFiber.go | 4 +- .../CWE-525/WebCacheDeceptionGoChi.go | 2 +- .../CWE-525/WebCacheDeceptionHTTPRouter.go | 2 +- go/ql/test/experimental/CWE-74/Dsn.go | 12 +- .../experimental/CWE-74/DsnInjection.qlref | 4 +- .../CWE-74/DsnInjectionLocal.qlref | 4 +- .../CWE-807/SensitiveConditionBypass.qlref | 3 +- .../CWE-807/SensitiveConditionBypassBad.go | 2 +- go/ql/test/experimental/CWE-807/condition.go | 6 +- .../CWE-840/ConditionalBypass.qlref | 3 +- .../CWE-840/ConditionalBypassBad.go | 2 +- go/ql/test/experimental/CWE-840/condition.go | 4 +- .../InconsistentCode/DeferInLoop.go | 2 +- .../InconsistentCode/DeferInLoop.qlref | 3 +- .../InconsistentCode/GORMErrorNotChecked.go | 2 +- .../GORMErrorNotChecked.qlref | 3 +- .../experimental/InconsistentCode/test.go | 10 +- .../Unsafe/WrongUsageOfUnsafe.expected | 24 +-- .../experimental/Unsafe/WrongUsageOfUnsafe.go | 24 +-- .../Unsafe/WrongUsageOfUnsafe.qlref | 3 +- .../go/frameworks/BeegoOrm/SqlInjection.qlref | 4 +- .../go/frameworks/BeegoOrm/StoredXss.qlref | 4 +- .../semmle/go/frameworks/BeegoOrm/test.go | 168 +++++++++--------- .../go/frameworks/Chi/ReflectedXss.qlref | 4 +- .../semmle/go/frameworks/Chi/test.go | 10 +- .../go/frameworks/Echo/OpenRedirect.qlref | 4 +- .../go/frameworks/Echo/ReflectedXss.qlref | 4 +- .../go/frameworks/Echo/TaintedPath.qlref | 4 +- .../semmle/go/frameworks/Echo/test.go | 92 +++++----- .../frameworks/GoMicro/LogInjection.expected | 4 +- .../go/frameworks/GoMicro/LogInjection.qlref | 3 +- .../semmle/go/frameworks/GoMicro/main.go | 4 +- .../CONSISTENCY/DataFlowConsistency.expected | 48 ++--- .../semmle/go/frameworks/Revel/EndToEnd.go | 17 +- .../go/frameworks/Revel/OpenRedirect.expected | 24 +-- .../go/frameworks/Revel/OpenRedirect.qlref | 4 +- .../go/frameworks/Revel/ReflectedXss.expected | 32 ++-- .../go/frameworks/Revel/ReflectedXss.qlref | 4 +- .../semmle/go/frameworks/Revel/Revel.go | 2 +- .../go/frameworks/Revel/TaintedPath.expected | 24 +-- .../go/frameworks/Revel/TaintedPath.qlref | 4 +- .../Revel/examples/booking/app/init.go | 4 +- .../go/frameworks/XNetHtml/ReflectedXss.qlref | 4 +- .../go/frameworks/XNetHtml/SqlInjection.qlref | 4 +- .../semmle/go/frameworks/XNetHtml/test.go | 50 +++--- .../ConstantLengthComparison.go | 2 +- .../ConstantLengthComparison.qlref | 3 +- .../InconsistentLoopOrientation.go | 2 +- .../InconsistentLoopOrientation.qlref | 3 +- .../InconsistentLoopOrientation/main.go | 6 +- .../LengthComparisonOffByOne.go | 4 +- .../LengthComparisonOffByOne.qlref | 3 +- .../LengthComparisonOffByOne/main.go | 8 +- .../MissingErrorCheck/MissingErrorCheck.qlref | 3 +- .../MissingErrorCheck/tests.go | 4 +- .../MistypedExponentiation.go | 2 +- .../MistypedExponentiation.qlref | 3 +- .../MistypedExponentiation/main.go | 10 +- .../WhitespaceContradictsPrecedence.go | 2 +- .../WhitespaceContradictsPrecedence.qlref | 3 +- .../WhitespaceContradictsPrecedence/main.go | 2 +- .../WrappedErrorAlwaysNil.go | 8 +- .../WrappedErrorAlwaysNil.qlref | 3 +- .../CompareIdenticalValues.go | 2 +- .../CompareIdenticalValues.qlref | 3 +- .../CompareIdenticalValues/tst.go | 4 +- .../CompareIdenticalValues/vp.go | 2 +- .../DeadStoreOfField/DeadStoreOfField.go | 2 +- .../DeadStoreOfField/DeadStoreOfField.qlref | 3 +- .../DeadStoreOfLocal/DeadStoreOfLocal.qlref | 3 +- .../RedundantCode/DeadStoreOfLocal/main.go | 2 +- .../DeadStoreOfLocal/testdata.go | 58 +++--- .../DuplicateBranches/DuplicateBranches.go | 2 +- .../DuplicateBranches/DuplicateBranches.qlref | 3 +- .../RedundantCode/DuplicateBranches/main.go | 2 +- .../DuplicateCondition/DuplicateCondition.go | 4 +- .../DuplicateCondition.qlref | 3 +- .../RedundantCode/DuplicateCondition/tst.go | 4 +- .../DuplicateSwitchCase.go | 2 +- .../DuplicateSwitchCase.qlref | 3 +- .../RedundantCode/DuplicateSwitchCase/tst.go | 2 +- .../ExprHasNoEffect/ExprHasNoEffect.go | 2 +- .../ExprHasNoEffect/ExprHasNoEffect.qlref | 3 +- .../RedundantCode/ExprHasNoEffect/main.go | 6 +- .../ImpossibleInterfaceNilCheck.go | 2 +- .../ImpossibleInterfaceNilCheck.qlref | 3 +- .../ImpossibleInterfaceNilCheck/tst.go | 2 +- .../NegativeLengthCheck.go | 2 +- .../NegativeLengthCheck.qlref | 3 +- .../RedundantCode/NegativeLengthCheck/main.go | 10 +- .../RedundantExpr/RedundantExpr.go | 2 +- .../RedundantExpr/RedundantExpr.qlref | 3 +- .../RedundantCode/RedundantExpr/tst.go | 4 +- .../RedundantRecover/RedundantRecover.qlref | 3 +- .../RedundantRecover/RedundantRecover1.go | 2 +- .../RedundantRecover/RedundantRecover2.go | 2 +- .../RedundantCode/RedundantRecover/tst.go | 2 +- .../SelfAssignment/SelfAssignment.go | 2 +- .../SelfAssignment/SelfAssignment.qlref | 3 +- .../RedundantCode/SelfAssignment/tst.go | 2 +- .../ShiftOutOfRange/ShiftOutOfRange.go | 2 +- .../ShiftOutOfRange/ShiftOutOfRange.qlref | 3 +- .../RedundantCode/ShiftOutOfRange/main.go | 6 +- .../UnreachableStatement.go | 2 +- .../UnreachableStatement.qlref | 3 +- .../UnreachableStatement/main.go | 22 +-- .../IncompleteHostnameRegexp.go | 4 +- .../IncompleteHostnameRegexp.qlref | 4 +- .../CWE-020/IncompleteHostnameRegexp/main.go | 14 +- .../IncompleteUrlSchemeCheck.go | 2 +- .../IncompleteUrlSchemeCheck.qlref | 3 +- .../CWE-020/IncompleteUrlSchemeCheck/main.go | 2 +- .../MissingRegexpAnchor.go | 2 +- .../MissingRegexpAnchor.qlref | 3 +- .../CWE-020/MissingRegexpAnchor/main.go | 20 +-- .../SuspiciousCharacterInRegexp.go | 2 +- .../SuspiciousCharacterInRegexp.qlref | 3 +- .../SuspiciousCharacterInRegexp/test.go | 20 +-- .../GorillaMuxDefault/TaintedPath.qlref | 4 +- .../CWE-022/GorillaMuxSkipClean/MuxClean.go | 4 +- .../GorillaMuxSkipClean/TaintedPath.qlref | 4 +- .../Security/CWE-022/TaintedPath.go | 8 +- .../Security/CWE-022/TaintedPath.qlref | 4 +- .../Security/CWE-022/UnsafeUnzipSymlink.go | 8 +- .../Security/CWE-022/UnsafeUnzipSymlink.qlref | 4 +- .../CWE-022/UnsafeUnzipSymlinkGood.go | 4 +- .../query-tests/Security/CWE-022/ZipSlip.go | 4 +- .../Security/CWE-022/ZipSlip.qlref | 4 +- .../query-tests/Security/CWE-022/tarslip.go | 4 +- .../test/query-tests/Security/CWE-022/tst.go | 4 +- .../Security/CWE-078/ArgumentInjection.go | 4 +- .../Security/CWE-078/CommandInjection.go | 4 +- .../Security/CWE-078/CommandInjection.qlref | 4 +- .../Security/CWE-078/CommandInjection2.go | 8 +- .../Security/CWE-078/GitSubcommands.go | 16 +- .../Security/CWE-078/SanitizingDoubleDash.go | 36 ++-- .../Security/CWE-078/StoredCommand.go | 4 +- .../Security/CWE-078/StoredCommand.qlref | 4 +- .../Security/CWE-089/SqlInjection.go | 4 +- .../Security/CWE-089/SqlInjection.qlref | 4 +- .../Security/CWE-089/StringBreak.go | 4 +- .../Security/CWE-089/StringBreak.qlref | 4 +- .../Security/CWE-089/StringBreakMismatched.go | 8 +- .../query-tests/Security/CWE-089/issue48.go | 12 +- .../test/query-tests/Security/CWE-089/main.go | 22 +-- .../query-tests/Security/CWE-089/mongoDB.go | 30 ++-- .../CWE-190/AllocationSizeOverflow.go | 4 +- .../CWE-190/AllocationSizeOverflow.qlref | 4 +- .../test/query-tests/Security/CWE-190/tst.go | 16 +- .../test/query-tests/Security/CWE-190/tst2.go | 8 +- .../test/query-tests/Security/CWE-190/tst3.go | 8 +- .../Security/CWE-209/StackTraceExposure.qlref | 3 +- .../test/query-tests/Security/CWE-209/test.go | 4 +- .../DisabledCertificateCheck.go | 2 +- .../DisabledCertificateCheck.qlref | 3 +- .../CWE-295/DisabledCertificateCheck/main.go | 6 +- .../CWE-322/InsecureHostKeyCallback.expected | 10 +- .../CWE-322/InsecureHostKeyCallback.qlref | 3 +- .../CWE-322/InsecureHostKeyCallbackExample.go | 12 +- .../Security/CWE-326/InsufficientKeySize.go | 22 +-- .../CWE-326/InsufficientKeySize.qlref | 3 +- .../query-tests/Security/CWE-327/UnsafeTLS.go | 94 +++++----- .../Security/CWE-327/UnsafeTLS.qlref | 4 +- .../InsecureRandomness/InsecureRandomness.go | 2 +- .../InsecureRandomness.qlref | 4 +- .../CWE-338/InsecureRandomness/sample.go | 14 +- .../CWE-347/MissingJwtSignatureCheck.qlref | 4 +- .../Security/CWE-347/go-jose.v3.go | 4 +- .../Security/CWE-347/golang-jwt-v5.go | 4 +- .../Security/CWE-352/ConstantOauth2State.go | 16 +- .../CWE-352/ConstantOauth2State.qlref | 3 +- .../BadRedirectCheck/BadRedirectCheck.go | 4 +- .../BadRedirectCheck/BadRedirectCheck.qlref | 4 +- .../Security/CWE-601/BadRedirectCheck/cves.go | 18 +- .../Security/CWE-601/BadRedirectCheck/main.go | 24 +-- .../Security/CWE-643/XPathInjection.go | 4 +- .../Security/CWE-643/XPathInjection.qlref | 4 +- .../test/query-tests/Security/CWE-643/tst.go | 90 +++++----- .../CWE-798/AlertSuppressionExample.go | 2 +- .../Security/CWE-798/HardcodedCredentials.go | 2 +- .../Security/CWE-798/HardcodedKeysBad.go | 2 +- .../test/query-tests/Security/CWE-798/jwt.go | 38 ++-- .../test/query-tests/Security/CWE-798/main.go | 2 +- .../query-tests/Security/CWE-798/sanitizer.go | 2 +- 207 files changed, 1011 insertions(+), 903 deletions(-) diff --git a/go/ql/src/experimental/CWE-525/WebCacheDeception.ql b/go/ql/src/experimental/CWE-525/WebCacheDeception.ql index eb488b0b0d1a..04faa7c29e11 100644 --- a/go/ql/src/experimental/CWE-525/WebCacheDeception.ql +++ b/go/ql/src/experimental/CWE-525/WebCacheDeception.ql @@ -1,4 +1,4 @@ -/* +/** * @name Web Cache Deception * @description A caching system has been detected on the application and is vulnerable to web cache deception. By manipulating the URL it is possible to force the application to cache pages that are only accessible by an authenticated user. Once cached, these pages can be accessed by an unauthenticated user. * @kind problem diff --git a/go/ql/test/experimental/CWE-090/LDAPInjection.go b/go/ql/test/experimental/CWE-090/LDAPInjection.go index 87741a08d28a..0acae7c0617b 100644 --- a/go/ql/test/experimental/CWE-090/LDAPInjection.go +++ b/go/ql/test/experimental/CWE-090/LDAPInjection.go @@ -54,31 +54,31 @@ func main() {} // bad is an example of a bad implementation func (ld *Ldap) bad(req *http.Request) { // ... - untrusted := req.UserAgent() + untrusted := req.UserAgent() // $ Source goldap.NewSearchRequest( - untrusted, // BAD: untrusted dn + untrusted, // $ Alert // BAD: untrusted dn goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false, - "(&(objectClass=organizationalPerson))"+untrusted, // BAD: untrusted filter - []string{"dn", "cn", untrusted}, // BAD: untrusted attribute + "(&(objectClass=organizationalPerson))"+untrusted, // $ Alert // BAD: untrusted filter + []string{"dn", "cn", untrusted}, // $ Alert // BAD: untrusted attribute nil, ) goldapv3.NewSearchRequest( - untrusted, // BAD: untrusted dn + untrusted, // $ Alert // BAD: untrusted dn goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false, - "(&(objectClass=organizationalPerson))"+untrusted, // BAD: untrusted filter - []string{"dn", "cn", untrusted}, // BAD: untrusted attribute + "(&(objectClass=organizationalPerson))"+untrusted, // $ Alert // BAD: untrusted filter + []string{"dn", "cn", untrusted}, // $ Alert // BAD: untrusted attribute nil, ) gopkgldapv2.NewSearchRequest( - untrusted, // BAD: untrusted dn + untrusted, // $ Alert // BAD: untrusted dn goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false, - "(&(objectClass=organizationalPerson))"+untrusted, // BAD: untrusted filter - []string{"dn", "cn", untrusted}, // BAD: untrusted attribute + "(&(objectClass=organizationalPerson))"+untrusted, // $ Alert // BAD: untrusted filter + []string{"dn", "cn", untrusted}, // $ Alert // BAD: untrusted attribute nil, ) client := &ldapclient.LDAPClient{} - client.Authenticate(untrusted, "123456") // BAD: untrusted filter - client.GetGroupsOfUser(untrusted) // BAD: untrusted filter + client.Authenticate(untrusted, "123456") // $ Alert // BAD: untrusted filter + client.GetGroupsOfUser(untrusted) // $ Alert // BAD: untrusted filter // ... } diff --git a/go/ql/test/experimental/CWE-090/LDAPInjection.qlref b/go/ql/test/experimental/CWE-090/LDAPInjection.qlref index 7049e09a7265..45935a174c4f 100644 --- a/go/ql/test/experimental/CWE-090/LDAPInjection.qlref +++ b/go/ql/test/experimental/CWE-090/LDAPInjection.qlref @@ -1,2 +1,4 @@ query: experimental/CWE-090/LDAPInjection.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/experimental/CWE-203/Timing.qlref b/go/ql/test/experimental/CWE-203/Timing.qlref index 7306096e724e..e14641beccfe 100644 --- a/go/ql/test/experimental/CWE-203/Timing.qlref +++ b/go/ql/test/experimental/CWE-203/Timing.qlref @@ -1,2 +1,4 @@ query: experimental/CWE-203/Timing.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/experimental/CWE-203/timing.go b/go/ql/test/experimental/CWE-203/timing.go index 43401bd4111c..32543e367b66 100644 --- a/go/ql/test/experimental/CWE-203/timing.go +++ b/go/ql/test/experimental/CWE-203/timing.go @@ -12,9 +12,9 @@ func bad(w http.ResponseWriter, req *http.Request) (interface{}, error) { secret := "MySuperSecretPasscode" secretHeader := "X-Secret" - headerSecret := req.Header.Get(secretHeader) + headerSecret := req.Header.Get(secretHeader) // $ Source secretStr := string(secret) - if len(headerSecret) != 0 && headerSecret != secretStr { + if len(headerSecret) != 0 && headerSecret != secretStr { // $ Alert return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret) } return nil, nil @@ -25,9 +25,9 @@ func bad2(w http.ResponseWriter, req *http.Request) (interface{}, error) { secret := "MySuperSecretPasscode" secretHeader := "X-Secret" - headerSecret := req.Header.Get(secretHeader) + headerSecret := req.Header.Get(secretHeader) // $ Source secretStr := string(secret) - if len(headerSecret) != 0 && strings.Compare(headerSecret, secretStr) != 0 { + if len(headerSecret) != 0 && strings.Compare(headerSecret, secretStr) != 0 { // $ Alert return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret) } return nil, nil @@ -38,8 +38,8 @@ func bad4(w http.ResponseWriter, req *http.Request) (interface{}, error) { secret := "MySuperSecretPasscode" secretHeader := "X-Secret" - headerSecret := req.Header.Get(secretHeader) - if len(secret) != 0 && headerSecret != "SecretStringLiteral" { + headerSecret := req.Header.Get(secretHeader) // $ Source + if len(secret) != 0 && headerSecret != "SecretStringLiteral" { // $ Alert return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret) } return nil, nil diff --git a/go/ql/test/experimental/CWE-285/PamAuthBypass.qlref b/go/ql/test/experimental/CWE-285/PamAuthBypass.qlref index 8a1d5b259e0b..85ba5b1005d3 100644 --- a/go/ql/test/experimental/CWE-285/PamAuthBypass.qlref +++ b/go/ql/test/experimental/CWE-285/PamAuthBypass.qlref @@ -1 +1,2 @@ -experimental/CWE-285/PamAuthBypass.ql \ No newline at end of file +query: experimental/CWE-285/PamAuthBypass.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/experimental/CWE-285/main.go b/go/ql/test/experimental/CWE-285/main.go index b0607a74a410..352a57bb6990 100644 --- a/go/ql/test/experimental/CWE-285/main.go +++ b/go/ql/test/experimental/CWE-285/main.go @@ -9,7 +9,7 @@ import ( func bad() error { t, _ := pam.StartFunc("", "", func(s pam.Style, msg string) (string, error) { return "", nil - }) + }) // $ Alert return t.Authenticate(0) } diff --git a/go/ql/test/experimental/CWE-287/ImproperLdapAuth.go b/go/ql/test/experimental/CWE-287/ImproperLdapAuth.go index b4e7b796b909..6e2f7d440337 100644 --- a/go/ql/test/experimental/CWE-287/ImproperLdapAuth.go +++ b/go/ql/test/experimental/CWE-287/ImproperLdapAuth.go @@ -15,7 +15,7 @@ func bad(w http.ResponseWriter, req *http.Request) (interface{}, error) { ldapServer := "ldap.example.com" ldapPort := 389 bindDN := "cn=admin,dc=example,dc=com" - bindPassword := req.URL.Query()["password"][0] + bindPassword := req.URL.Query()["password"][0] // $ Source // Connect to the LDAP server l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort)) @@ -25,7 +25,7 @@ func bad(w http.ResponseWriter, req *http.Request) (interface{}, error) { defer l.Close() // BAD: user input is not sanetized - err = l.Bind(bindDN, bindPassword) + err = l.Bind(bindDN, bindPassword) // $ Alert if err != nil { return fmt.Errorf("LDAP bind failed: %v", err), err } @@ -84,7 +84,7 @@ func bad2(req *http.Request) { ldapPort := 389 bindDN := "cn=admin,dc=example,dc=com" // BAD : empty password - bindPassword := "" + bindPassword := "" // $ Source // Connect to the LDAP server l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort)) @@ -94,7 +94,7 @@ func bad2(req *http.Request) { defer l.Close() // BAD : bindPassword is empty - err = l.Bind(bindDN, bindPassword) + err = l.Bind(bindDN, bindPassword) // $ Alert if err != nil { log.Fatalf("LDAP bind failed: %v", err) } diff --git a/go/ql/test/experimental/CWE-287/ImproperLdapAuth.qlref b/go/ql/test/experimental/CWE-287/ImproperLdapAuth.qlref index 35ca7800cc8a..409b5b3347db 100644 --- a/go/ql/test/experimental/CWE-287/ImproperLdapAuth.qlref +++ b/go/ql/test/experimental/CWE-287/ImproperLdapAuth.qlref @@ -1,2 +1,4 @@ query: experimental/CWE-287/ImproperLdapAuth.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/experimental/CWE-321-V2/HardCodedKeys.expected b/go/ql/test/experimental/CWE-321-V2/HardCodedKeys.expected index 5b26a2a9b369..0cad327e6415 100644 --- a/go/ql/test/experimental/CWE-321-V2/HardCodedKeys.expected +++ b/go/ql/test/experimental/CWE-321-V2/HardCodedKeys.expected @@ -1,3 +1,6 @@ +#select +| go-jose.v3.go:24:32:24:37 | JwtKey | go-jose.v3.go:13:21:13:33 | "AllYourBase" | go-jose.v3.go:24:32:24:37 | JwtKey | This $@. | go-jose.v3.go:13:21:13:33 | "AllYourBase" | Constant Key is used as JWT Secret key | +| golang-jwt-v5.go:27:9:27:15 | JwtKey1 | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | golang-jwt-v5.go:27:9:27:15 | JwtKey1 | This $@. | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | Constant Key is used as JWT Secret key | edges | go-jose.v3.go:13:14:13:34 | type conversion | go-jose.v3.go:24:32:24:37 | JwtKey | provenance | | | go-jose.v3.go:13:21:13:33 | "AllYourBase" | go-jose.v3.go:13:14:13:34 | type conversion | provenance | | @@ -11,6 +14,3 @@ nodes | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | semmle.label | "AllYourBase" | | golang-jwt-v5.go:27:9:27:15 | JwtKey1 | semmle.label | JwtKey1 | subpaths -#select -| go-jose.v3.go:24:32:24:37 | JwtKey | go-jose.v3.go:13:21:13:33 | "AllYourBase" | go-jose.v3.go:24:32:24:37 | JwtKey | This $@. | go-jose.v3.go:13:21:13:33 | "AllYourBase" | Constant Key is used as JWT Secret key | -| golang-jwt-v5.go:27:9:27:15 | JwtKey1 | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | golang-jwt-v5.go:27:9:27:15 | JwtKey1 | This $@. | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | Constant Key is used as JWT Secret key | diff --git a/go/ql/test/experimental/CWE-321-V2/HardCodedKeys.qlref b/go/ql/test/experimental/CWE-321-V2/HardCodedKeys.qlref index e6cee5464208..63827b14d7aa 100644 --- a/go/ql/test/experimental/CWE-321-V2/HardCodedKeys.qlref +++ b/go/ql/test/experimental/CWE-321-V2/HardCodedKeys.qlref @@ -1 +1,2 @@ -experimental/CWE-321-V2/HardCodedKeys.ql \ No newline at end of file +query: experimental/CWE-321-V2/HardCodedKeys.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/experimental/CWE-321-V2/go-jose.v3.go b/go/ql/test/experimental/CWE-321-V2/go-jose.v3.go index e25624bb680f..c9d103710bad 100644 --- a/go/ql/test/experimental/CWE-321-V2/go-jose.v3.go +++ b/go/ql/test/experimental/CWE-321-V2/go-jose.v3.go @@ -10,7 +10,7 @@ import ( ) // NOT OK -var JwtKey = []byte("AllYourBase") +var JwtKey = []byte("AllYourBase") // $ Source func main2(r *http.Request) { signedToken := r.URL.Query().Get("signedToken") @@ -21,7 +21,7 @@ func verifyJWT(signedToken string) { fmt.Println("verifying JWT") DecodedToken, _ := jwt.ParseSigned(signedToken) out := CustomerInfo{} - if err := DecodedToken.Claims(JwtKey, &out); err != nil { + if err := DecodedToken.Claims(JwtKey, &out); err != nil { // $ Alert panic(err) } fmt.Printf("%v\n", out) diff --git a/go/ql/test/experimental/CWE-321-V2/golang-jwt-v5.go b/go/ql/test/experimental/CWE-321-V2/golang-jwt-v5.go index 71917160bdaa..166c8e6454e9 100644 --- a/go/ql/test/experimental/CWE-321-V2/golang-jwt-v5.go +++ b/go/ql/test/experimental/CWE-321-V2/golang-jwt-v5.go @@ -16,7 +16,7 @@ type CustomerInfo struct { } // BAD constant key -var JwtKey1 = []byte("AllYourBase") +var JwtKey1 = []byte("AllYourBase") // $ Source func main1(r *http.Request) { signedToken := r.URL.Query().Get("signedToken") @@ -24,7 +24,7 @@ func main1(r *http.Request) { } func LoadJwtKey(token *jwt.Token) (interface{}, error) { - return JwtKey1, nil + return JwtKey1, nil // $ Alert } func verifyJWT_golangjwt(signedToken string) { diff --git a/go/ql/test/experimental/CWE-369/DivideByZero.go b/go/ql/test/experimental/CWE-369/DivideByZero.go index 613479981b1e..75588a18b458 100644 --- a/go/ql/test/experimental/CWE-369/DivideByZero.go +++ b/go/ql/test/experimental/CWE-369/DivideByZero.go @@ -7,37 +7,37 @@ import ( ) func myHandler1(w http.ResponseWriter, r *http.Request) { - param1 := r.URL.Query()["param1"][0] + param1 := r.URL.Query()["param1"][0] // $ Source value, _ := strconv.Atoi(param1) - out := 1337 / value + out := 1337 / value // $ Alert fmt.Println(out) } func myHandler2(w http.ResponseWriter, r *http.Request) { - param1 := r.URL.Query()["param1"][0] + param1 := r.URL.Query()["param1"][0] // $ Source value := int(param1[0]) - out := 1337 / value + out := 1337 / value // $ Alert fmt.Println(out) } func myHandler3(w http.ResponseWriter, r *http.Request) { - param1 := r.URL.Query()["param1"][0] + param1 := r.URL.Query()["param1"][0] // $ Source value, _ := strconv.ParseInt(param1, 10, 64) - out := 1337 / value + out := 1337 / value // $ Alert fmt.Println(out) } func myHandler4(w http.ResponseWriter, r *http.Request) { - param1 := r.URL.Query()["param1"][0] + param1 := r.URL.Query()["param1"][0] // $ Source value, _ := strconv.ParseFloat(param1, 32) - out := 1337 / value + out := 1337 / value // $ Alert fmt.Println(out) } func myHandler5(w http.ResponseWriter, r *http.Request) { - param1 := r.URL.Query()["param1"][0] + param1 := r.URL.Query()["param1"][0] // $ Source value, _ := strconv.ParseUint(param1, 10, 64) - out := 1337 / value + out := 1337 / value // $ Alert fmt.Println(out) } @@ -51,10 +51,10 @@ func myHandler6(w http.ResponseWriter, r *http.Request) { } func myHandler7(w http.ResponseWriter, r *http.Request) { - param1 := r.URL.Query()["param1"][0] + param1 := r.URL.Query()["param1"][0] // $ Source value := int(param1[0]) if value >= 0 { - out := 1337 / value + out := 1337 / value // $ Alert fmt.Println(out) } } diff --git a/go/ql/test/experimental/CWE-369/DivideByZero.qlref b/go/ql/test/experimental/CWE-369/DivideByZero.qlref index 80eca2d32193..0713092d4b8a 100644 --- a/go/ql/test/experimental/CWE-369/DivideByZero.qlref +++ b/go/ql/test/experimental/CWE-369/DivideByZero.qlref @@ -1,2 +1,4 @@ query: experimental/CWE-369/DivideByZero.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.expected b/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.expected index 074dfaa134f6..e95505223cd7 100644 --- a/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.expected +++ b/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.expected @@ -1,3 +1,7 @@ +#select +| DatabaseCallInLoop.go:9:3:9:41 | call to First | DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First | This calls call to First in a $@. | DatabaseCallInLoop.go:7:2:11:2 | range statement | loop | +| test.go:11:2:11:13 | call to Take | test.go:20:2:22:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:20:2:22:2 | for statement | loop | +| test.go:11:2:11:13 | call to Take | test.go:24:2:26:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:24:2:26:2 | for statement | loop | edges | DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First | | test.go:10:1:12:1 | function declaration | test.go:11:2:11:13 | call to Take | @@ -7,7 +11,3 @@ edges | test.go:21:3:21:14 | call to runQuery | test.go:10:1:12:1 | function declaration | | test.go:24:2:26:2 | for statement | test.go:25:3:25:17 | call to runRunQuery | | test.go:25:3:25:17 | call to runRunQuery | test.go:14:1:16:1 | function declaration | -#select -| DatabaseCallInLoop.go:9:3:9:41 | call to First | DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First | This calls call to First in a $@. | DatabaseCallInLoop.go:7:2:11:2 | range statement | loop | -| test.go:11:2:11:13 | call to Take | test.go:20:2:22:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:20:2:22:2 | for statement | loop | -| test.go:11:2:11:13 | call to Take | test.go:24:2:26:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:24:2:26:2 | for statement | loop | diff --git a/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.go b/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.go index 138bbbcd9d48..eff08179ee5a 100644 --- a/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.go +++ b/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.go @@ -6,8 +6,8 @@ func getUsers(db *gorm.DB, names []string) []User { res := make([]User, 0, len(names)) for _, name := range names { var user User - db.Where("name = ?", name).First(&user) + db.Where("name = ?", name).First(&user) // $ Alert res = append(res, user) - } + } // $ Source return res } diff --git a/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.qlref b/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.qlref index 63f27c9b41fc..945fbc88364e 100644 --- a/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.qlref +++ b/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.qlref @@ -1 +1,2 @@ -experimental/CWE-400/DatabaseCallInLoop.ql +query: experimental/CWE-400/DatabaseCallInLoop.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/experimental/CWE-400/test.go b/go/ql/test/experimental/CWE-400/test.go index 725fb541b386..4c0a7f01d2eb 100644 --- a/go/ql/test/experimental/CWE-400/test.go +++ b/go/ql/test/experimental/CWE-400/test.go @@ -8,7 +8,7 @@ type User struct { } func runQuery(db *gorm.DB) { - db.Take(nil) + db.Take(nil) // $ Alert } func runRunQuery(db *gorm.DB) { @@ -19,9 +19,9 @@ func main() { var db *gorm.DB for i := 0; i < 10; i++ { runQuery(db) - } + } // $ Source for i := 10; i > 0; i-- { runRunQuery(db) - } + } // $ Source } diff --git a/go/ql/test/experimental/CWE-522-DecompressionBombs/DecompressionBombs.qlref b/go/ql/test/experimental/CWE-522-DecompressionBombs/DecompressionBombs.qlref index 93d41075d5f3..367d7bfe2fd5 100644 --- a/go/ql/test/experimental/CWE-522-DecompressionBombs/DecompressionBombs.qlref +++ b/go/ql/test/experimental/CWE-522-DecompressionBombs/DecompressionBombs.qlref @@ -1,2 +1,4 @@ query: experimental/CWE-522-DecompressionBombs/DecompressionBombs.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/experimental/CWE-522-DecompressionBombs/test.go b/go/ql/test/experimental/CWE-522-DecompressionBombs/test.go index dc359c387ac9..370b24d4d3e8 100644 --- a/go/ql/test/experimental/CWE-522-DecompressionBombs/test.go +++ b/go/ql/test/experimental/CWE-522-DecompressionBombs/test.go @@ -56,41 +56,41 @@ func main() { func DecompressHandler(w http.ResponseWriter, request *http.Request) { GZipOpenReaderSafe(request.PostFormValue("test")) ZipOpenReaderSafe(request.PostFormValue("test")) - ZipOpenReader(request.FormValue("filepath")) - ZipNewReader(request.Body) - ZipNewReaderKlauspost(request.Body) - Bzip2Dsnet(request.Body) + ZipOpenReader(request.FormValue("filepath")) // $ Source + ZipNewReader(request.Body) // $ Source + ZipNewReaderKlauspost(request.Body) // $ Source + Bzip2Dsnet(request.Body) // $ Source Bzip2DsnetSafe(request.Body) - Bzip2(request.Body) + Bzip2(request.Body) // $ Source Bzip2Safe(request.Body) - Flate(request.Body) + Flate(request.Body) // $ Source FlateSafe(request.Body) - FlateKlauspost(request.Body) + FlateKlauspost(request.Body) // $ Source FlateKlauspostSafe(request.Body) - FlateDsnet(request.Body) + FlateDsnet(request.Body) // $ Source FlateDsnetSafe(request.Body) - ZlibKlauspost(request.Body) + ZlibKlauspost(request.Body) // $ Source ZlibKlauspostSafe(request.Body) - Zlib(request.Body) + Zlib(request.Body) // $ Source ZlibSafe(request.Body) - Snappy(request.Body) + Snappy(request.Body) // $ Source SnappySafe(request.Body) - SnappyKlauspost(request.Body) + SnappyKlauspost(request.Body) // $ Source SnappyKlauspostSafe(request.Body) - S2(request.Body) + S2(request.Body) // $ Source S2Safe(request.Body) - Gzip(request.Body) + Gzip(request.Body) // $ Source GzipSafe(request.Body) - GZipIoReader(request.Body, "dest") - GzipKlauspost(request.Body) + GZipIoReader(request.Body, "dest") // $ Source + GzipKlauspost(request.Body) // $ Source GzipKlauspostSafe(request.Body) - PzipKlauspost(request.Body) + PzipKlauspost(request.Body) // $ Source PzipKlauspostSafe(request.Body) - Zstd_Klauspost(request.Body) + Zstd_Klauspost(request.Body) // $ Source Zstd_KlauspostSafe(request.Body) - Zstd_DataDog(request.Body) + Zstd_DataDog(request.Body) // $ Source Zstd_DataDogSafe(request.Body) - Xz(request.Body) + Xz(request.Body) // $ Source XzSafe(request.Body) } @@ -131,7 +131,7 @@ func ZipOpenReader(filename string) { for _, f := range zipReader.File { rc, _ := f.Open() for { - result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc" + result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc" Alert if result == 0 { _ = rc.Close() break @@ -144,7 +144,7 @@ func ZipOpenReader(filename string) { for _, f := range zipKlauspostReader.File { rc, _ := f.Open() for { - result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc" + result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc" Alert if result == 0 { _ = rc.Close() break @@ -161,7 +161,7 @@ func ZipNewReader(file io.Reader) { for _, file := range zipReader.File { fileWriter := bytes.NewBuffer([]byte{}) fileReaderCloser, _ := file.Open() - result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser" + result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser" Alert fmt.Print(result) } } @@ -173,7 +173,7 @@ func ZipNewReaderKlauspost(file io.Reader) { fileWriter := bytes.NewBuffer([]byte{}) // file.OpenRaw() fileReaderCloser, _ := file.Open() - result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser" + result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser" Alert fmt.Print(result) } } @@ -183,7 +183,7 @@ func Bzip2Dsnet(file io.Reader) { bzip2Reader, _ := bzip2Dsnet.NewReader(file, &bzip2Dsnet.ReaderConfig{}) var out []byte = make([]byte, 70) - bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader" + bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader" Alert tarRead = tar.NewReader(bzip2Reader) TarDecompressor(tarRead) @@ -210,7 +210,7 @@ func Bzip2(file io.Reader) { bzip2Reader := bzip2.NewReader(file) var out []byte = make([]byte, 70) - bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader" + bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader" Alert tarRead = tar.NewReader(bzip2Reader) TarDecompressor(tarRead) @@ -235,7 +235,7 @@ func Flate(file io.Reader) { flateReader := flate.NewReader(file) var out []byte = make([]byte, 70) - flateReader.Read(out) // $ hasValueFlow="flateReader" + flateReader.Read(out) // $ hasValueFlow="flateReader" Alert tarRead = tar.NewReader(flateReader) TarDecompressor(tarRead) @@ -260,7 +260,7 @@ func FlateKlauspost(file io.Reader) { flateReader := flateKlauspost.NewReader(file) var out []byte = make([]byte, 70) - flateReader.Read(out) // $ hasValueFlow="flateReader" + flateReader.Read(out) // $ hasValueFlow="flateReader" Alert tarRead = tar.NewReader(flateReader) TarDecompressor(tarRead) @@ -285,7 +285,7 @@ func FlateDsnet(file io.Reader) { flateReader, _ := flateDsnet.NewReader(file, &flateDsnet.ReaderConfig{}) var out []byte = make([]byte, 70) - flateReader.Read(out) // $ hasValueFlow="flateReader" + flateReader.Read(out) // $ hasValueFlow="flateReader" Alert tarRead = tar.NewReader(flateReader) TarDecompressor(tarRead) @@ -310,7 +310,7 @@ func ZlibKlauspost(file io.Reader) { zlibReader, _ := zlibKlauspost.NewReader(file) var out []byte = make([]byte, 70) - zlibReader.Read(out) // $ hasValueFlow="zlibReader" + zlibReader.Read(out) // $ hasValueFlow="zlibReader" Alert tarRead = tar.NewReader(zlibReader) TarDecompressor(tarRead) @@ -335,7 +335,7 @@ func Zlib(file io.Reader) { zlibReader, _ := zlib.NewReader(file) var out []byte = make([]byte, 70) - zlibReader.Read(out) // $ hasValueFlow="zlibReader" + zlibReader.Read(out) // $ hasValueFlow="zlibReader" Alert tarRead = tar.NewReader(zlibReader) TarDecompressor(tarRead) @@ -360,8 +360,8 @@ func Snappy(file io.Reader) { snappyReader := snappy.NewReader(file) var out []byte = make([]byte, 70) - snappyReader.Read(out) // $ hasValueFlow="snappyReader" - snappyReader.ReadByte() // $ hasValueFlow="snappyReader" + snappyReader.Read(out) // $ hasValueFlow="snappyReader" Alert + snappyReader.ReadByte() // $ hasValueFlow="snappyReader" Alert tarRead = tar.NewReader(snappyReader) TarDecompressor(tarRead) @@ -386,10 +386,10 @@ func SnappyKlauspost(file io.Reader) { snappyReader := snappyKlauspost.NewReader(file) var out []byte = make([]byte, 70) - snappyReader.Read(out) // $ hasValueFlow="snappyReader" + snappyReader.Read(out) // $ hasValueFlow="snappyReader" Alert var buf bytes.Buffer - snappyReader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="snappyReader" - snappyReader.ReadByte() // $ hasValueFlow="snappyReader" + snappyReader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="snappyReader" Alert + snappyReader.ReadByte() // $ hasValueFlow="snappyReader" Alert tarRead = tar.NewReader(snappyReader) TarDecompressor(tarRead) @@ -414,10 +414,10 @@ func S2(file io.Reader) { s2Reader := s2.NewReader(file) var out []byte = make([]byte, 70) - s2Reader.Read(out) // $ hasValueFlow="s2Reader" - s2Reader.ReadByte() // $ hasValueFlow="s2Reader" + s2Reader.Read(out) // $ hasValueFlow="s2Reader" Alert + s2Reader.ReadByte() // $ hasValueFlow="s2Reader" Alert var buf bytes.Buffer - s2Reader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="s2Reader" + s2Reader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="s2Reader" Alert tarRead = tar.NewReader(s2Reader) TarDecompressor(tarRead) @@ -442,14 +442,14 @@ func GZipIoReader(src io.Reader, dst string) { dstF, _ := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) defer dstF.Close() newSrc := io.Reader(gzipReader) - _, _ = io.Copy(dstF, newSrc) // $ hasValueFlow="newSrc" + _, _ = io.Copy(dstF, newSrc) // $ hasValueFlow="newSrc" Alert } func Gzip(file io.Reader) { var tarRead *tar.Reader gzipReader, _ := gzip.NewReader(file) var out []byte = make([]byte, 70) - gzipReader.Read(out) // $ hasValueFlow="gzipReader" + gzipReader.Read(out) // $ hasValueFlow="gzipReader" Alert tarRead = tar.NewReader(gzipReader) TarDecompressor(tarRead) @@ -474,9 +474,9 @@ func GzipKlauspost(file io.Reader) { gzipReader, _ := gzipKlauspost.NewReader(file) var out []byte = make([]byte, 70) - gzipReader.Read(out) // $ hasValueFlow="gzipReader" + gzipReader.Read(out) // $ hasValueFlow="gzipReader" Alert var buf bytes.Buffer - gzipReader.WriteTo(&buf) // $ hasValueFlow="gzipReader" + gzipReader.WriteTo(&buf) // $ hasValueFlow="gzipReader" Alert tarRead = tar.NewReader(gzipReader) TarDecompressor(tarRead) @@ -501,9 +501,9 @@ func PzipKlauspost(file io.Reader) { pgzipReader, _ := pgzipKlauspost.NewReader(file) var out []byte = make([]byte, 70) - pgzipReader.Read(out) // $ hasValueFlow="pgzipReader" + pgzipReader.Read(out) // $ hasValueFlow="pgzipReader" Alert var buf bytes.Buffer - pgzipReader.WriteTo(&buf) // $ hasValueFlow="pgzipReader" + pgzipReader.WriteTo(&buf) // $ hasValueFlow="pgzipReader" Alert tarRead = tar.NewReader(pgzipReader) TarDecompressor(tarRead) @@ -528,11 +528,11 @@ func Zstd_Klauspost(file io.Reader) { zstdReader, _ := zstdKlauspost.NewReader(file) var out []byte = make([]byte, 70) - zstdReader.Read(out) // $ hasValueFlow="zstdReader" + zstdReader.Read(out) // $ hasValueFlow="zstdReader" Alert var buf bytes.Buffer - zstdReader.WriteTo(&buf) // $ hasValueFlow="zstdReader" + zstdReader.WriteTo(&buf) // $ hasValueFlow="zstdReader" Alert var src []byte - zstdReader.DecodeAll(src, nil) // $ hasValueFlow="zstdReader" + zstdReader.DecodeAll(src, nil) // $ hasValueFlow="zstdReader" Alert tarRead = tar.NewReader(zstdReader) TarDecompressor(tarRead) @@ -557,7 +557,7 @@ func Zstd_DataDog(file io.Reader) { zstdReader := zstdDataDog.NewReader(file) var out []byte = make([]byte, 70) - zstdReader.Read(out) // $ hasValueFlow="zstdReader" + zstdReader.Read(out) // $ hasValueFlow="zstdReader" Alert tarRead = tar.NewReader(zstdReader) TarDecompressor(tarRead) @@ -582,7 +582,7 @@ func Xz(file io.Reader) { xzReader, _ := xz.NewReader(file) var out []byte = make([]byte, 70) - xzReader.Read(out) // $ hasValueFlow="xzReader" + xzReader.Read(out) // $ hasValueFlow="xzReader" Alert tarRead = tar.NewReader(xzReader) fmt.Println(io.SeekStart) @@ -618,7 +618,7 @@ func TarDecompressor(tarRead *tar.Reader) { if cur.Typeflag != tar.TypeReg { continue } - data, _ := io.ReadAll(tarRead) // $ hasValueFlow="tarRead" + data, _ := io.ReadAll(tarRead) // $ hasValueFlow="tarRead" Alert files[cur.Name] = &fstest.MapFile{Data: data} } fmt.Print(files) @@ -626,7 +626,7 @@ func TarDecompressor(tarRead *tar.Reader) { func TarDecompressor2(tarRead *tar.Reader) { var tarOut []byte = make([]byte, 70) - tarRead.Read(tarOut) // $ hasValueFlow="tarRead" + tarRead.Read(tarOut) // $ hasValueFlow="tarRead" Alert fmt.Println("do sth with output:", tarOut) } diff --git a/go/ql/test/experimental/CWE-525/WebCacheDeception.qlref b/go/ql/test/experimental/CWE-525/WebCacheDeception.qlref index 8b0788ef904d..9e5d5cc3033d 100644 --- a/go/ql/test/experimental/CWE-525/WebCacheDeception.qlref +++ b/go/ql/test/experimental/CWE-525/WebCacheDeception.qlref @@ -1 +1,2 @@ -experimental/CWE-525/WebCacheDeception.ql \ No newline at end of file +query: experimental/CWE-525/WebCacheDeception.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/experimental/CWE-525/WebCacheDeceptionBad.go b/go/ql/test/experimental/CWE-525/WebCacheDeceptionBad.go index 577fbd78c062..978d05588bbf 100644 --- a/go/ql/test/experimental/CWE-525/WebCacheDeceptionBad.go +++ b/go/ql/test/experimental/CWE-525/WebCacheDeceptionBad.go @@ -79,7 +79,7 @@ func badRoutingNet() { http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/")))) - http.HandleFunc("/adminusers/", ShowAdminPageCache) + http.HandleFunc("/adminusers/", ShowAdminPageCache) // $ Alert err := http.ListenAndServe(":1337", nil) if err != nil { log.Fatal("ListenAndServe: ", err) diff --git a/go/ql/test/experimental/CWE-525/WebCacheDeceptionFiber.go b/go/ql/test/experimental/CWE-525/WebCacheDeceptionFiber.go index 80f396c26dfd..1126659d76e3 100644 --- a/go/ql/test/experimental/CWE-525/WebCacheDeceptionFiber.go +++ b/go/ql/test/experimental/CWE-525/WebCacheDeceptionFiber.go @@ -12,12 +12,12 @@ func badRouting() { log.Println("We are logging in Golang!") // GET /api/register - app.Get("/api/*", func(c *fiber.Ctx) error { + app.Get("/api/*", func(c *fiber.Ctx) error { // $ Alert msg := fmt.Sprintf("✋") return c.SendString(msg) // => ✋ register }) - app.Post("/api/*", func(c *fiber.Ctx) error { + app.Post("/api/*", func(c *fiber.Ctx) error { // $ Alert msg := fmt.Sprintf("✋") return c.SendString(msg) // => ✋ register }) diff --git a/go/ql/test/experimental/CWE-525/WebCacheDeceptionGoChi.go b/go/ql/test/experimental/CWE-525/WebCacheDeceptionGoChi.go index 539dae1dee99..3de5e659138f 100644 --- a/go/ql/test/experimental/CWE-525/WebCacheDeceptionGoChi.go +++ b/go/ql/test/experimental/CWE-525/WebCacheDeceptionGoChi.go @@ -10,7 +10,7 @@ import ( func badRoutingChi() { r := chi.NewRouter() r.Use(middleware.Logger) - r.Get("/*", func(w http.ResponseWriter, r *http.Request) { + r.Get("/*", func(w http.ResponseWriter, r *http.Request) { // $ Alert w.Write([]byte("welcome")) }) http.ListenAndServe(":3000", r) diff --git a/go/ql/test/experimental/CWE-525/WebCacheDeceptionHTTPRouter.go b/go/ql/test/experimental/CWE-525/WebCacheDeceptionHTTPRouter.go index 864c6c5e31cd..7d1cd0b3d16e 100644 --- a/go/ql/test/experimental/CWE-525/WebCacheDeceptionHTTPRouter.go +++ b/go/ql/test/experimental/CWE-525/WebCacheDeceptionHTTPRouter.go @@ -18,7 +18,7 @@ func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { func badHTTPRouter() { router := httprouter.New() - router.GET("/test/*test", Index) + router.GET("/test/*test", Index) // $ Alert router.GET("/hello/:name", Hello) log.Fatal(http.ListenAndServe(":8082", router)) diff --git a/go/ql/test/experimental/CWE-74/Dsn.go b/go/ql/test/experimental/CWE-74/Dsn.go index 3cdabc7cb3f2..56eee4a48eea 100644 --- a/go/ql/test/experimental/CWE-74/Dsn.go +++ b/go/ql/test/experimental/CWE-74/Dsn.go @@ -23,10 +23,10 @@ func good() (interface{}, error) { } func bad() interface{} { - name2 := os.Args[1:] + name2 := os.Args[1:] // $ Source[go/dsn-injection-local] // This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files. dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, name2[0]) - db, _ := sql.Open("mysql", dbDSN) + db, _ := sql.Open("mysql", dbDSN) // $ Alert[go/dsn-injection-local] return db } @@ -44,10 +44,10 @@ func good2(w http.ResponseWriter, req *http.Request) (interface{}, error) { } func bad2(w http.ResponseWriter, req *http.Request) interface{} { - name := req.FormValue("name") + name := req.FormValue("name") // $ Source[go/dsn-injection] // This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files. dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, name) - db, _ := sql.Open("mysql", dbDSN) + db, _ := sql.Open("mysql", dbDSN) // $ Alert[go/dsn-injection] return db } @@ -60,12 +60,12 @@ func (Config) Parse([]string) error { return nil } func RegexFuncModelTest(w http.ResponseWriter, req *http.Request) (interface{}, error) { cfg := NewConfig() - err := cfg.Parse(os.Args[1:]) // This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files. + err := cfg.Parse(os.Args[1:]) // $ Source[go/dsn-injection-local] // This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files. if err != nil { return nil, err } dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, cfg.dsn) - db, _ := sql.Open("mysql", dbDSN) + db, _ := sql.Open("mysql", dbDSN) // $ Alert[go/dsn-injection-local] return db, nil } diff --git a/go/ql/test/experimental/CWE-74/DsnInjection.qlref b/go/ql/test/experimental/CWE-74/DsnInjection.qlref index f8e0117d7351..1b4688980783 100644 --- a/go/ql/test/experimental/CWE-74/DsnInjection.qlref +++ b/go/ql/test/experimental/CWE-74/DsnInjection.qlref @@ -1,2 +1,4 @@ query: experimental/CWE-74/DsnInjection.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/experimental/CWE-74/DsnInjectionLocal.qlref b/go/ql/test/experimental/CWE-74/DsnInjectionLocal.qlref index f2d6116c7f1e..f0907dee9395 100644 --- a/go/ql/test/experimental/CWE-74/DsnInjectionLocal.qlref +++ b/go/ql/test/experimental/CWE-74/DsnInjectionLocal.qlref @@ -1,2 +1,4 @@ query: experimental/CWE-74/DsnInjectionLocal.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/experimental/CWE-807/SensitiveConditionBypass.qlref b/go/ql/test/experimental/CWE-807/SensitiveConditionBypass.qlref index da2ab35074a6..b31f535387ef 100644 --- a/go/ql/test/experimental/CWE-807/SensitiveConditionBypass.qlref +++ b/go/ql/test/experimental/CWE-807/SensitiveConditionBypass.qlref @@ -1 +1,2 @@ -experimental/CWE-807/SensitiveConditionBypass.ql +query: experimental/CWE-807/SensitiveConditionBypass.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/experimental/CWE-807/SensitiveConditionBypassBad.go b/go/ql/test/experimental/CWE-807/SensitiveConditionBypassBad.go index bf8e70f88b76..04161f28fa84 100644 --- a/go/ql/test/experimental/CWE-807/SensitiveConditionBypassBad.go +++ b/go/ql/test/experimental/CWE-807/SensitiveConditionBypassBad.go @@ -4,7 +4,7 @@ import "net/http" func example(w http.ResponseWriter, r *http.Request) { test2 := "test" - if r.Header.Get("X-Password") != test2 { + if r.Header.Get("X-Password") != test2 { // $ Alert login() } } diff --git a/go/ql/test/experimental/CWE-807/condition.go b/go/ql/test/experimental/CWE-807/condition.go index ecd6b0a9f2a8..d2bef8b335b5 100644 --- a/go/ql/test/experimental/CWE-807/condition.go +++ b/go/ql/test/experimental/CWE-807/condition.go @@ -13,7 +13,7 @@ const test = "localhost" // Should alert as authkey is sensitive func ex1(w http.ResponseWriter, r *http.Request) { - if r.Header.Get("Origin") != test { + if r.Header.Get("Origin") != test { // $ Alert authkey := "randomDatta" io.WriteString(w, authkey) } @@ -22,7 +22,7 @@ func ex1(w http.ResponseWriter, r *http.Request) { // Should alert as authkey is sensitive func ex2(w http.ResponseWriter, r *http.Request) { test2 := "test" - if r.Header.Get("Origin") != test2 { + if r.Header.Get("Origin") != test2 { // $ Alert authkey := "randomDatta2" io.WriteString(w, authkey) } @@ -31,7 +31,7 @@ func ex2(w http.ResponseWriter, r *http.Request) { // Should alert as login() is sensitive func ex3(w http.ResponseWriter, r *http.Request) { test2 := "test" - if r.Header.Get("Origin") != test2 { + if r.Header.Get("Origin") != test2 { // $ Alert login() } } diff --git a/go/ql/test/experimental/CWE-840/ConditionalBypass.qlref b/go/ql/test/experimental/CWE-840/ConditionalBypass.qlref index 6d1676160552..8c99cf7c2856 100644 --- a/go/ql/test/experimental/CWE-840/ConditionalBypass.qlref +++ b/go/ql/test/experimental/CWE-840/ConditionalBypass.qlref @@ -1 +1,2 @@ -experimental/CWE-840/ConditionalBypass.ql +query: experimental/CWE-840/ConditionalBypass.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/experimental/CWE-840/ConditionalBypassBad.go b/go/ql/test/experimental/CWE-840/ConditionalBypassBad.go index b788dee2009c..a90b723e8be0 100644 --- a/go/ql/test/experimental/CWE-840/ConditionalBypassBad.go +++ b/go/ql/test/experimental/CWE-840/ConditionalBypassBad.go @@ -6,7 +6,7 @@ import ( func exampleHandlerBad(w http.ResponseWriter, r *http.Request) { // BAD: the Origin and Host headers are user controlled - if r.Header.Get("Origin") != "http://"+r.Host { + if r.Header.Get("Origin") != "http://"+r.Host { // $ Alert //do something } } diff --git a/go/ql/test/experimental/CWE-840/condition.go b/go/ql/test/experimental/CWE-840/condition.go index 7b7b7480c104..fa413f325767 100644 --- a/go/ql/test/experimental/CWE-840/condition.go +++ b/go/ql/test/experimental/CWE-840/condition.go @@ -6,14 +6,14 @@ import ( // BAD: taken from https://www.gorillatoolkit.org/pkg/websocket func ex1(w http.ResponseWriter, r *http.Request) { - if r.Header.Get("Origin") != "http://"+r.Host { + if r.Header.Get("Origin") != "http://"+r.Host { // $ Alert //do something } } // BAD: both operands are from remote sources func ex2(w http.ResponseWriter, r *http.Request) { - if r.Header.Get("Origin") != "http://"+r.Header.Get("Header") { + if r.Header.Get("Origin") != "http://"+r.Header.Get("Header") { // $ Alert //do something } } diff --git a/go/ql/test/experimental/InconsistentCode/DeferInLoop.go b/go/ql/test/experimental/InconsistentCode/DeferInLoop.go index 1b57d1855b40..476a72a68f96 100644 --- a/go/ql/test/experimental/InconsistentCode/DeferInLoop.go +++ b/go/ql/test/experimental/InconsistentCode/DeferInLoop.go @@ -5,7 +5,7 @@ import "os" func openFiles(filenames []string) { for _, filename := range filenames { file, err := os.Open(filename) - defer file.Close() + defer file.Close() // $ Alert[go/examples/deferinloop] if err != nil { // handle error } diff --git a/go/ql/test/experimental/InconsistentCode/DeferInLoop.qlref b/go/ql/test/experimental/InconsistentCode/DeferInLoop.qlref index e50bcf4fdf62..f291f77e09ec 100644 --- a/go/ql/test/experimental/InconsistentCode/DeferInLoop.qlref +++ b/go/ql/test/experimental/InconsistentCode/DeferInLoop.qlref @@ -1 +1,2 @@ -experimental/InconsistentCode/DeferInLoop.ql +query: experimental/InconsistentCode/DeferInLoop.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.go b/go/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.go index 422e49b5f105..c24f9bad5a7d 100644 --- a/go/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.go +++ b/go/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.go @@ -4,6 +4,6 @@ import "gorm.io/gorm" func getUserId(db *gorm.DB, name string) int64 { var user User - db.Where("name = ?", name).First(&user) + db.Where("name = ?", name).First(&user) // $ Alert[go/examples/gorm-error-not-checked] return user.Id } diff --git a/go/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.qlref b/go/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.qlref index b52256ad5391..20b8106442bf 100644 --- a/go/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.qlref +++ b/go/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.qlref @@ -1 +1,2 @@ -experimental/InconsistentCode/GORMErrorNotChecked.ql +query: experimental/InconsistentCode/GORMErrorNotChecked.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/experimental/InconsistentCode/test.go b/go/ql/test/experimental/InconsistentCode/test.go index 1dc64350bd41..ec893a14e74a 100644 --- a/go/ql/test/experimental/InconsistentCode/test.go +++ b/go/ql/test/experimental/InconsistentCode/test.go @@ -3,24 +3,24 @@ package main func test() { var xs []int for _ = range xs { - defer test() // not ok + defer test() // $ Alert[go/examples/deferinloop] // not ok } for _ = range xs { if true { - defer test() // not ok + defer test() // $ Alert[go/examples/deferinloop] // not ok } } for i := 0; i < 10; i++ { - defer test() + defer test() // $ Alert[go/examples/deferinloop] } for true { - defer test() // not ok + defer test() // $ Alert[go/examples/deferinloop] // not ok } for false { - defer test() // fine but caught + defer test() // $ Alert[go/examples/deferinloop] // fine but caught } } diff --git a/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.expected b/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.expected index 3c7e02eea265..0dfdf1d7c150 100644 --- a/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.expected +++ b/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.expected @@ -1,3 +1,15 @@ +#select +| WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | $@. | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | Dangerous array type casting to [8]uint8 from an index expression ([8]uint8)[2] (the destination type is 2 elements longer) | +| WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | $@. | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | Dangerous array type casting to [17]uint8 from an index expression ([8]uint8)[0] (the destination type is 9 elements longer) | +| WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | $@. | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | +| WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | $@. | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | +| WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | $@. | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | Dangerous array type casting to [17]string from [8]string | +| WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | $@. | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | Dangerous type up-casting to [17]uint8 from struct type | +| WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | $@. | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | +| WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | $@. | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | +| WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | $@. | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | Dangerous array type casting to [4]int64 from [1]int64 | +| WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | $@. | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | Dangerous numeric type casting to int64 from int8 | +| WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | $@. | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | Dangerous numeric type casting to int from int8 | edges | WrongUsageOfUnsafe.go:17:24:17:48 | type conversion | WrongUsageOfUnsafe.go:17:13:17:49 | type conversion | provenance | | | WrongUsageOfUnsafe.go:34:24:34:51 | type conversion | WrongUsageOfUnsafe.go:34:13:34:52 | type conversion | provenance | | @@ -48,15 +60,3 @@ nodes | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | semmle.label | type conversion | subpaths -#select -| WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | $@. | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | Dangerous array type casting to [8]uint8 from an index expression ([8]uint8)[2] (the destination type is 2 elements longer) | -| WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | $@. | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | Dangerous array type casting to [17]uint8 from an index expression ([8]uint8)[0] (the destination type is 9 elements longer) | -| WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | $@. | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | -| WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | $@. | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | -| WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | $@. | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | Dangerous array type casting to [17]string from [8]string | -| WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | $@. | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | Dangerous type up-casting to [17]uint8 from struct type | -| WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | $@. | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | -| WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | $@. | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | -| WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | $@. | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | Dangerous array type casting to [4]int64 from [1]int64 | -| WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | $@. | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | Dangerous numeric type casting to int64 from int8 | -| WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | $@. | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | Dangerous numeric type casting to int from int8 | diff --git a/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.go b/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.go index 8599550039a6..f20b72895899 100644 --- a/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.go +++ b/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.go @@ -74,7 +74,7 @@ func badIndexExpr() { // the address of the 3rd element of the `harmless` array, // and continue for 8 bytes, going out of the boundaries of // `harmless` and crossing into the memory occupied by `secret`. - var leaking = (*[8]byte)(unsafe.Pointer(&harmless[2])) // BAD + var leaking = (*[8]byte)(unsafe.Pointer(&harmless[2])) // $ Alert // BAD fmt.Println(string((*leaking)[:])) @@ -108,7 +108,7 @@ func bad0() { // Read before secret, overflowing into secret // (notice we get the pointer to the first byte of harmless) - var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless[0])) // BAD + var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless[0])) // $ Alert // BAD fmt.Println(string((*leaking)[:])) @@ -126,7 +126,7 @@ func bad1() { // Read before secret, overflowing into secret // (notice we read more than the length of harmless) - var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // BAD + var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // $ Alert // BAD fmt.Println(string((*leaking)[:])) @@ -146,7 +146,7 @@ func bad2() { // Read before secret, overflowing into secret // (notice we read more than the length of harmless) - var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // BAD + var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // $ Alert // BAD fmt.Println(string((*leaking)[:])) @@ -163,7 +163,7 @@ func bad3() { // Read before secret, overflowing into secret // (notice we read more than the length of harmless) - var leaking = (*[8 + 9]string)(unsafe.Pointer(&harmless)) // BAD + var leaking = (*[8 + 9]string)(unsafe.Pointer(&harmless)) // $ Alert // BAD fmt.Println(*leaking) fmt.Println([17]string((*leaking))) @@ -186,7 +186,7 @@ func bad4() { // Read before secret, overflowing into secret // (notice we read more than the length of harmless) - var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // BAD + var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // $ Alert // BAD fmt.Println(string((*leaking)[:])) @@ -208,7 +208,7 @@ func bad5() { // Read before secret, overflowing into secret // (notice we read more than the length of harmless) - var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless.Data)) // BAD + var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless.Data)) // $ Alert // BAD fmt.Println(string(leaking[:])) @@ -224,7 +224,7 @@ func bad6() { secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'} // Read before secret: - var leaking = buffer_request(unsafe.Pointer(&harmless)) // BAD (see inside buffer_request func) + var leaking = buffer_request(unsafe.Pointer(&harmless)) // $ Source // BAD (see inside buffer_request func) fmt.Println((string)(leaking[:])) @@ -240,7 +240,7 @@ func buffer_request(req unsafe.Pointer) [8 + 9]byte { // will be read, the read will also contain pieces of // data from `secret`. var buf [8 + 9]byte - buf = *(*[8 + 9]byte)(req) // BAD (from above func) + buf = *(*[8 + 9]byte)(req) // $ Alert // BAD (from above func) return buf } func bad7() { @@ -253,7 +253,7 @@ func bad7() { // (notice we read more than the length of harmless); // the leaking array will not contain letters, // but integers representing bytes from `secret`. - var leaking = (*[4]int64)(unsafe.Pointer(&harmless)) // BAD + var leaking = (*[4]int64)(unsafe.Pointer(&harmless)) // $ Alert // BAD fmt.Println(*leaking) @@ -271,7 +271,7 @@ func bad8() { // Read before secret, overflowing into secret // (notice we read more than the length of harmless); // the leaking data will contain some bits from `secret`. - var leaking = (*int64)(unsafe.Pointer(&harmless)) // BAD + var leaking = (*int64)(unsafe.Pointer(&harmless)) // $ Alert // BAD fmt.Println(*leaking) @@ -289,7 +289,7 @@ func bad9() { // Read before secret, overflowing into secret // (notice we read more than the length of harmless); // the leaking data will contain some bits from `secret`. - var leaking = (*int)(unsafe.Pointer(&harmless)) // BAD + var leaking = (*int)(unsafe.Pointer(&harmless)) // $ Alert // BAD fmt.Println(*leaking) diff --git a/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.qlref b/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.qlref index 2f5c54707c76..5496859ca2e8 100644 --- a/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.qlref +++ b/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.qlref @@ -1 +1,2 @@ -experimental/Unsafe/WrongUsageOfUnsafe.ql +query: experimental/Unsafe/WrongUsageOfUnsafe.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.qlref b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.qlref index b6916bd2cd46..e19181577447 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.qlref +++ b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.qlref @@ -1,2 +1,4 @@ query: Security/CWE-089/SqlInjection.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/StoredXss.qlref b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/StoredXss.qlref index 66b7d67dd8f3..f47ad25ca9c7 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/StoredXss.qlref +++ b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/StoredXss.qlref @@ -1,2 +1,4 @@ query: Security/CWE-079/StoredXss.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/test.go b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/test.go index cce152e57ef8..5dacd494c05d 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/test.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/test.go @@ -8,61 +8,61 @@ import ( // BAD: using untrusted data in SQL queries func testDbMethods(bdb *orm.DB, untrustedSource *http.Request) { - untrusted := untrustedSource.UserAgent() - - bdb.Exec(untrusted) // $ querystring=untrusted - bdb.ExecContext(nil, untrusted) // $ querystring=untrusted - bdb.Prepare(untrusted) // $ querystring=untrusted - bdb.PrepareContext(nil, untrusted) // $ querystring=untrusted - bdb.Query(untrusted) // $ querystring=untrusted - bdb.QueryContext(nil, untrusted) // $ querystring=untrusted - bdb.QueryRow(untrusted) // $ querystring=untrusted - bdb.QueryRowContext(nil, untrusted) // $ querystring=untrusted + untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection] + + bdb.Exec(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + bdb.ExecContext(nil, untrusted) // $ querystring=untrusted Alert[go/sql-injection] + bdb.Prepare(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + bdb.PrepareContext(nil, untrusted) // $ querystring=untrusted Alert[go/sql-injection] + bdb.Query(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + bdb.QueryContext(nil, untrusted) // $ querystring=untrusted Alert[go/sql-injection] + bdb.QueryRow(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + bdb.QueryRowContext(nil, untrusted) // $ querystring=untrusted Alert[go/sql-injection] } // BAD: using untrusted data to build SQL queries (QueryBuilder does not sanitize its arguments) func testQueryBuilderMethods(qb orm.QueryBuilder, untrustedSource *http.Request) { - untrusted := untrustedSource.UserAgent() - untrusted2 := untrustedSource.UserAgent() - - qb.Select(untrusted) // $ querystring=untrusted - qb.From(untrusted) // $ querystring=untrusted - qb.InnerJoin(untrusted) // $ querystring=untrusted - qb.LeftJoin(untrusted) // $ querystring=untrusted - qb.RightJoin(untrusted) // $ querystring=untrusted - qb.On(untrusted) // $ querystring=untrusted - qb.Where(untrusted) // $ querystring=untrusted - qb.And(untrusted) // $ querystring=untrusted - qb.Or(untrusted) // $ querystring=untrusted - qb.In(untrusted) // $ querystring=untrusted - qb.OrderBy(untrusted) // $ querystring=untrusted - qb.GroupBy(untrusted) // $ querystring=untrusted - qb.Having(untrusted) // $ querystring=untrusted - qb.Update(untrusted) // $ querystring=untrusted - qb.Set(untrusted) // $ querystring=untrusted - qb.Delete(untrusted) // $ querystring=untrusted - qb.InsertInto(untrusted, untrusted2) // $ querystring=untrusted querystring=untrusted2 - qb.Values(untrusted) // $ querystring=untrusted - qb.Subquery(untrusted, untrusted2) // $ querystring=untrusted querystring=untrusted2 + untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection] + untrusted2 := untrustedSource.UserAgent() // $ Source[go/sql-injection] + + qb.Select(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.From(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.InnerJoin(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.LeftJoin(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.RightJoin(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.On(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.Where(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.And(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.Or(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.In(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.OrderBy(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.GroupBy(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.Having(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.Update(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.Set(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.Delete(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.InsertInto(untrusted, untrusted2) // $ querystring=untrusted querystring=untrusted2 Alert[go/sql-injection] + qb.Values(untrusted) // $ querystring=untrusted Alert[go/sql-injection] + qb.Subquery(untrusted, untrusted2) // $ querystring=untrusted querystring=untrusted2 Alert[go/sql-injection] } func testOrmerRaw(ormer orm.Ormer, untrustedSource *http.Request) { - untrusted := untrustedSource.UserAgent() + untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection] untrusted2 := untrustedSource.UserAgent() - ormer.Raw(untrusted, untrusted2) // $ querystring=untrusted // BAD: using an untrusted string as a query + ormer.Raw(untrusted, untrusted2) // $ querystring=untrusted Alert[go/sql-injection] // BAD: using an untrusted string as a query ormer.Raw("FROM ? SELECT ?", untrusted, untrusted2) // $ querystring="FROM ? SELECT ?" // GOOD: untrusted string used in argument context } func testFilterRaw(querySeter orm.QuerySeter, untrustedSource *http.Request) { - untrusted := untrustedSource.UserAgent() - querySeter.FilterRaw(untrusted, "safe") // $ querystring="safe" // GOOD: untrusted used as a column name - querySeter.FilterRaw("safe", untrusted) // $ querystring=untrusted // BAD: untrusted used as a SQL fragment + untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection] + querySeter.FilterRaw(untrusted, "safe") // $ querystring="safe" // GOOD: untrusted used as a column name + querySeter.FilterRaw("safe", untrusted) // $ querystring=untrusted Alert[go/sql-injection] // BAD: untrusted used as a SQL fragment } func testConditionRaw(cond orm.Condition, untrustedSource *http.Request) { - untrusted := untrustedSource.UserAgent() - cond.Raw(untrusted, "safe") // $ querystring="safe" // GOOD: untrusted used as a column name - cond.Raw("safe", untrusted) // $ querystring=untrusted // BAD: untrusted used as a SQL fragment + untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection] + cond.Raw(untrusted, "safe") // $ querystring="safe" // GOOD: untrusted used as a column name + cond.Raw("safe", untrusted) // $ querystring=untrusted Alert[go/sql-injection] // BAD: untrusted used as a SQL fragment } type SubStruct struct { @@ -77,90 +77,90 @@ type MyStruct struct { // BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response func testOrmerReads(ormer orm.Ormer, sink http.ResponseWriter) { obj := MyStruct{} - ormer.Read(&obj) - sink.Write([]byte(obj.field)) - sink.Write([]byte(obj.substructs[0].field)) + ormer.Read(&obj) // $ Source[go/stored-xss] + sink.Write([]byte(obj.field)) // $ Alert[go/stored-xss] + sink.Write([]byte(obj.substructs[0].field)) // $ Alert[go/stored-xss] obj2 := MyStruct{} - ormer.ReadForUpdate(&obj2) - sink.Write([]byte(obj2.field)) + ormer.ReadForUpdate(&obj2) // $ Source[go/stored-xss] + sink.Write([]byte(obj2.field)) // $ Alert[go/stored-xss] obj3 := MyStruct{} - ormer.ReadOrCreate(&obj3, "arg") - sink.Write([]byte(obj3.field)) + ormer.ReadOrCreate(&obj3, "arg") // $ Source[go/stored-xss] + sink.Write([]byte(obj3.field)) // $ Alert[go/stored-xss] } // BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response func testFieldReads(textField *orm.TextField, jsonField *orm.JSONField, jsonbField *orm.JsonbField, sink http.ResponseWriter) { - sink.Write([]byte(textField.Value())) - sink.Write([]byte(textField.RawValue().(string))) - sink.Write([]byte(textField.String())) - sink.Write([]byte(jsonField.Value())) - sink.Write([]byte(jsonField.RawValue().(string))) - sink.Write([]byte(jsonField.String())) - sink.Write([]byte(jsonbField.Value())) - sink.Write([]byte(jsonbField.RawValue().(string))) - sink.Write([]byte(jsonbField.String())) + sink.Write([]byte(textField.Value())) // $ Alert[go/stored-xss] + sink.Write([]byte(textField.RawValue().(string))) // $ Alert[go/stored-xss] + sink.Write([]byte(textField.String())) // $ Alert[go/stored-xss] + sink.Write([]byte(jsonField.Value())) // $ Alert[go/stored-xss] + sink.Write([]byte(jsonField.RawValue().(string))) // $ Alert[go/stored-xss] + sink.Write([]byte(jsonField.String())) // $ Alert[go/stored-xss] + sink.Write([]byte(jsonbField.Value())) // $ Alert[go/stored-xss] + sink.Write([]byte(jsonbField.RawValue().(string))) // $ Alert[go/stored-xss] + sink.Write([]byte(jsonbField.String())) // $ Alert[go/stored-xss] } // BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response func testQuerySeterReads(qs orm.QuerySeter, sink http.ResponseWriter) { var objs []*MyStruct - qs.All(&objs) - sink.Write([]byte(objs[0].field)) + qs.All(&objs) // $ Source[go/stored-xss] + sink.Write([]byte(objs[0].field)) // $ Alert[go/stored-xss] var obj MyStruct - qs.One(&obj) - sink.Write([]byte(obj.field)) + qs.One(&obj) // $ Source[go/stored-xss] + sink.Write([]byte(obj.field)) // $ Alert[go/stored-xss] var allMaps []orm.Params - qs.Values(&allMaps) - sink.Write([]byte(allMaps[0]["field"].(string))) + qs.Values(&allMaps) // $ Source[go/stored-xss] + sink.Write([]byte(allMaps[0]["field"].(string))) // $ Alert[go/stored-xss] var allLists []orm.ParamsList - qs.ValuesList(&allLists) - sink.Write([]byte(allLists[0][0].(string))) + qs.ValuesList(&allLists) // $ Source[go/stored-xss] + sink.Write([]byte(allLists[0][0].(string))) // $ Alert[go/stored-xss] var oneList orm.ParamsList - qs.ValuesFlat(&oneList, "colname") - sink.Write([]byte(oneList[0].(string))) + qs.ValuesFlat(&oneList, "colname") // $ Source[go/stored-xss] + sink.Write([]byte(oneList[0].(string))) // $ Alert[go/stored-xss] var oneRowMap orm.Params - qs.RowsToMap(&oneRowMap, "key", "value") - sink.Write([]byte(oneRowMap["field"].(string))) + qs.RowsToMap(&oneRowMap, "key", "value") // $ Source[go/stored-xss] + sink.Write([]byte(oneRowMap["field"].(string))) // $ Alert[go/stored-xss] var oneRowStruct MyStruct - qs.RowsToStruct(&oneRowStruct, "key", "value") - sink.Write([]byte(oneRowStruct.field)) + qs.RowsToStruct(&oneRowStruct, "key", "value") // $ Source[go/stored-xss] + sink.Write([]byte(oneRowStruct.field)) // $ Alert[go/stored-xss] } // BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response func testRawSeterReads(rs orm.RawSeter, sink http.ResponseWriter) { var allMaps []orm.Params - rs.Values(&allMaps) - sink.Write([]byte(allMaps[0]["field"].(string))) + rs.Values(&allMaps) // $ Source[go/stored-xss] + sink.Write([]byte(allMaps[0]["field"].(string))) // $ Alert[go/stored-xss] var allLists []orm.ParamsList - rs.ValuesList(&allLists) - sink.Write([]byte(allLists[0][0].(string))) + rs.ValuesList(&allLists) // $ Source[go/stored-xss] + sink.Write([]byte(allLists[0][0].(string))) // $ Alert[go/stored-xss] var oneList orm.ParamsList - rs.ValuesFlat(&oneList, "colname") - sink.Write([]byte(oneList[0].(string))) + rs.ValuesFlat(&oneList, "colname") // $ Source[go/stored-xss] + sink.Write([]byte(oneList[0].(string))) // $ Alert[go/stored-xss] var oneRowMap orm.Params - rs.RowsToMap(&oneRowMap, "key", "value") - sink.Write([]byte(oneRowMap["field"].(string))) + rs.RowsToMap(&oneRowMap, "key", "value") // $ Source[go/stored-xss] + sink.Write([]byte(oneRowMap["field"].(string))) // $ Alert[go/stored-xss] var oneRowStruct MyStruct - rs.RowsToStruct(&oneRowStruct, "key", "value") - sink.Write([]byte(oneRowStruct.field)) + rs.RowsToStruct(&oneRowStruct, "key", "value") // $ Source[go/stored-xss] + sink.Write([]byte(oneRowStruct.field)) // $ Alert[go/stored-xss] var strField string - rs.QueryRow(&strField) - sink.Write([]byte(strField)) + rs.QueryRow(&strField) // $ Source[go/stored-xss] + sink.Write([]byte(strField)) // $ Alert[go/stored-xss] var strFields []string - rs.QueryRows(&strFields) - sink.Write([]byte(strFields[0])) + rs.QueryRows(&strFields) // $ Source[go/stored-xss] + sink.Write([]byte(strFields[0])) // $ Alert[go/stored-xss] } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Chi/ReflectedXss.qlref b/go/ql/test/library-tests/semmle/go/frameworks/Chi/ReflectedXss.qlref index 754513d72bb3..e6b791f39fca 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Chi/ReflectedXss.qlref +++ b/go/ql/test/library-tests/semmle/go/frameworks/Chi/ReflectedXss.qlref @@ -1,2 +1,4 @@ query: Security/CWE-079/ReflectedXss.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Chi/test.go b/go/ql/test/library-tests/semmle/go/frameworks/Chi/test.go index f02e0cdfb15a..aeb33fe8af00 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Chi/test.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/Chi/test.go @@ -10,7 +10,7 @@ var hidden string func hideUserData(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - hidden = r.URL.Path + hidden = r.URL.Path // $ Source next.ServeHTTP(w, r) }) } @@ -18,10 +18,10 @@ func hideUserData(next http.Handler) http.Handler { func main() { r := chi.NewRouter() r.With(hideUserData).Get("/", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(hidden)) - w.Write([]byte(chi.URLParam(r, "someParam"))) - w.Write([]byte(chi.URLParamFromCtx(r.Context(), "someKey"))) - w.Write([]byte(chi.RouteContext(r.Context()).URLParam("someOtherKey"))) + w.Write([]byte(hidden)) // $ Alert + w.Write([]byte(chi.URLParam(r, "someParam"))) // $ Alert + w.Write([]byte(chi.URLParamFromCtx(r.Context(), "someKey"))) // $ Alert + w.Write([]byte(chi.RouteContext(r.Context()).URLParam("someOtherKey"))) // $ Alert }) http.ListenAndServe(":3000", r) } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.qlref b/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.qlref index 867dd7665618..13add930f517 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.qlref +++ b/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.qlref @@ -1,2 +1,4 @@ query: Security/CWE-601/OpenUrlRedirect.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Echo/ReflectedXss.qlref b/go/ql/test/library-tests/semmle/go/frameworks/Echo/ReflectedXss.qlref index 754513d72bb3..e6b791f39fca 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Echo/ReflectedXss.qlref +++ b/go/ql/test/library-tests/semmle/go/frameworks/Echo/ReflectedXss.qlref @@ -1,2 +1,4 @@ query: Security/CWE-079/ReflectedXss.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Echo/TaintedPath.qlref b/go/ql/test/library-tests/semmle/go/frameworks/Echo/TaintedPath.qlref index 78ce25b1921f..6eb2e94892f2 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Echo/TaintedPath.qlref +++ b/go/ql/test/library-tests/semmle/go/frameworks/Echo/TaintedPath.qlref @@ -1,2 +1,4 @@ query: Security/CWE-022/TaintedPath.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Echo/test.go b/go/ql/test/library-tests/semmle/go/frameworks/Echo/test.go index 4a9f4e161f62..2435d91c6d7f 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Echo/test.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/Echo/test.go @@ -12,81 +12,81 @@ import ( // All are XSS vulnerabilities, except as specifically noted. func testParam(ctx echo.Context) error { - param := ctx.Param("someParam") - ctx.HTML(200, param) + param := ctx.Param("someParam") // $ Source[go/reflected-xss] + ctx.HTML(200, param) // $ Alert[go/reflected-xss] return nil } func testParamValues(ctx echo.Context) error { - param := ctx.ParamValues()[0] - ctx.HTML(200, param) + param := ctx.ParamValues()[0] // $ Source[go/reflected-xss] + ctx.HTML(200, param) // $ Alert[go/reflected-xss] return nil } func testQueryParam(ctx echo.Context) error { - param := ctx.QueryParam("someParam") - ctx.HTML(200, param) + param := ctx.QueryParam("someParam") // $ Source[go/reflected-xss] + ctx.HTML(200, param) // $ Alert[go/reflected-xss] return nil } func testQueryParams(ctx echo.Context) error { - param := ctx.QueryParams()["someParam"][0] - ctx.HTML(200, param) + param := ctx.QueryParams()["someParam"][0] // $ Source[go/reflected-xss] + ctx.HTML(200, param) // $ Alert[go/reflected-xss] return nil } func testQueryString(ctx echo.Context) error { - qstr := ctx.QueryString() - ctx.HTML(200, qstr) + qstr := ctx.QueryString() // $ Source[go/reflected-xss] + ctx.HTML(200, qstr) // $ Alert[go/reflected-xss] return nil } func testFormValue(ctx echo.Context) error { - val := ctx.FormValue("someField") - ctx.HTML(200, val) + val := ctx.FormValue("someField") // $ Source[go/reflected-xss] + ctx.HTML(200, val) // $ Alert[go/reflected-xss] return nil } func testFormParams(ctx echo.Context) error { - params, _ := ctx.FormParams() - ctx.HTML(200, params["someField"][0]) + params, _ := ctx.FormParams() // $ Source[go/reflected-xss] + ctx.HTML(200, params["someField"][0]) // $ Alert[go/reflected-xss] return nil } func testFormFile(ctx echo.Context) error { - fileHeader, _ := ctx.FormFile("someFilename") + fileHeader, _ := ctx.FormFile("someFilename") // $ Source[go/reflected-xss] file, _ := fileHeader.Open() buffer := make([]byte, 100) file.Read(buffer) - ctx.HTMLBlob(200, buffer) + ctx.HTMLBlob(200, buffer) // $ Alert[go/reflected-xss] return nil } func testMultipartFormValue(ctx echo.Context) error { - form, _ := ctx.MultipartForm() - ctx.HTML(200, form.Value["someField"][0]) + form, _ := ctx.MultipartForm() // $ Source[go/reflected-xss] + ctx.HTML(200, form.Value["someField"][0]) // $ Alert[go/reflected-xss] return nil } func testMultipartFormFile(ctx echo.Context) error { - form, _ := ctx.MultipartForm() + form, _ := ctx.MultipartForm() // $ Source[go/reflected-xss] fileHeader := form.File["someFilename"][0] file, _ := fileHeader.Open() buffer := make([]byte, 100) file.Read(buffer) - ctx.HTMLBlob(200, buffer) + ctx.HTMLBlob(200, buffer) // $ Alert[go/reflected-xss] return nil } func testCookie(ctx echo.Context) error { - val, _ := ctx.Cookie("someKey") - ctx.HTML(200, val.Value) + val, _ := ctx.Cookie("someKey") // $ Source[go/reflected-xss] + ctx.HTML(200, val.Value) // $ Alert[go/reflected-xss] return nil } func testCookies(ctx echo.Context) error { - cookies := ctx.Cookies() - ctx.HTML(200, cookies[0].Value) + cookies := ctx.Cookies() // $ Source[go/reflected-xss] + ctx.HTML(200, cookies[0].Value) // $ Alert[go/reflected-xss] return nil } @@ -96,8 +96,8 @@ type myStruct struct { func testBind(ctx echo.Context) error { data := myStruct{} - ctx.Bind(&data) - ctx.HTML(200, data.s) + ctx.Bind(&data) // $ Source[go/reflected-xss] + ctx.HTML(200, data.s) // $ Alert[go/reflected-xss] return nil } @@ -110,8 +110,8 @@ func testGetSetEmpty(ctx echo.Context) error { } func testGetSet(ctx echo.Context) error { - ctx.Set("someKey", ctx.Param("someParam")) - ctx.HTML(200, ctx.Get("someKey").(string)) // BAD, the context is tainted + ctx.Set("someKey", ctx.Param("someParam")) // $ Source[go/reflected-xss] + ctx.HTML(200, ctx.Get("someKey").(string)) // $ Alert[go/reflected-xss] // BAD, the context is tainted return nil } @@ -121,20 +121,20 @@ func testGetSet(ctx echo.Context) error { // All are XSS vulnerabilities, except as specifically noted. func testHTML(ctx echo.Context) error { - param := ctx.Param("someParam") - ctx.HTML(200, param) + param := ctx.Param("someParam") // $ Source[go/reflected-xss] + ctx.HTML(200, param) // $ Alert[go/reflected-xss] return nil } func testHTMLBlob(ctx echo.Context) error { - param := ctx.Param("someParam") - ctx.HTMLBlob(200, []byte(param)) + param := ctx.Param("someParam") // $ Source[go/reflected-xss] + ctx.HTMLBlob(200, []byte(param)) // $ Alert[go/reflected-xss] return nil } func testBlob(ctx echo.Context) error { - param := ctx.Param("someParam") - ctx.Blob(200, "text/html", []byte(param)) // BAD, the content-type is HTML + param := ctx.Param("someParam") // $ Source[go/reflected-xss] + ctx.Blob(200, "text/html", []byte(param)) // $ Alert[go/reflected-xss] // BAD, the content-type is HTML return nil } @@ -145,9 +145,9 @@ func testBlobSafe(ctx echo.Context) error { } func testStream(ctx echo.Context) error { - param := ctx.Param("someParam") + param := ctx.Param("someParam") // $ Source[go/reflected-xss] reader := strings.NewReader(param) - ctx.Stream(200, "text/html", reader) // BAD, the content-type is HTML + ctx.Stream(200, "text/html", reader) // $ Alert[go/reflected-xss] // BAD, the content-type is HTML return nil } @@ -161,28 +161,28 @@ func testStreamSafe(ctx echo.Context) error { // Section: testing output methods defined on Response (XSS vulnerability) func testResponseWrite(ctx echo.Context) error { - param := ctx.Param("someParam") - ctx.Response().Write([]byte(param)) + param := ctx.Param("someParam") // $ Source[go/reflected-xss] + ctx.Response().Write([]byte(param)) // $ Alert[go/reflected-xss] return nil } // Section: test detecting an open redirect using the Context.Redirect function: func testRedirect(ctx echo.Context) error { - param := ctx.Param("someParam") - ctx.Redirect(301, param) + param := ctx.Param("someParam") // $ Source[go/unvalidated-url-redirection] + ctx.Redirect(301, param) // $ Alert[go/unvalidated-url-redirection] return nil } func testLocalRedirects(ctx echo.Context) error { - param := ctx.Param("someParam") + param := ctx.Param("someParam") // $ Source[go/unvalidated-url-redirection] param2 := param param3 := param // Gratuitous copy because sanitization of uses propagates to subsequent uses // GOOD: local redirects are unproblematic ctx.Redirect(301, "/local"+param) // BAD: this could be a non-local redirect - ctx.Redirect(301, "/"+param2) + ctx.Redirect(301, "/"+param2) // $ Alert[go/unvalidated-url-redirection] // GOOD: localhost redirects are unproblematic ctx.Redirect(301, "//localhost/"+param3) return nil @@ -221,12 +221,12 @@ func testNonExploitableFields(ctx echo.Context) error { func fsOpsTest() { e := echo.New() e.GET("/", func(c echo.Context) error { - filepath := c.QueryParam("filePath") - return c.File(filepath) // $ FileSystemAccess=filepath + filepath := c.QueryParam("filePath") // $ Source[go/path-injection] + return c.File(filepath) // $ FileSystemAccess=filepath Alert[go/path-injection] }) e.GET("/attachment", func(c echo.Context) error { - filepath := c.QueryParam("filePath") - return c.Attachment(filepath, "file name in response") // $ FileSystemAccess=filepath + filepath := c.QueryParam("filePath") // $ Source[go/path-injection] + return c.Attachment(filepath, "file name in response") // $ FileSystemAccess=filepath Alert[go/path-injection] }) _ = e.Start(":1323") } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/LogInjection.expected b/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/LogInjection.expected index 703066d64494..4ec65220a529 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/LogInjection.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/LogInjection.expected @@ -1,8 +1,8 @@ +#select +| main.go:21:28:21:31 | name | main.go:18:46:18:48 | definition of req | main.go:21:28:21:31 | name | This log entry depends on a $@. | main.go:18:46:18:48 | definition of req | user-provided value | edges | main.go:18:46:18:48 | definition of req | main.go:21:28:21:31 | name | provenance | | nodes | main.go:18:46:18:48 | definition of req | semmle.label | definition of req | | main.go:21:28:21:31 | name | semmle.label | name | subpaths -#select -| main.go:21:28:21:31 | name | main.go:18:46:18:48 | definition of req | main.go:21:28:21:31 | name | This log entry depends on a $@. | main.go:18:46:18:48 | definition of req | user-provided value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/LogInjection.qlref b/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/LogInjection.qlref index 1837c628c33e..fc8a61c453d2 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/LogInjection.qlref +++ b/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/LogInjection.qlref @@ -1 +1,2 @@ -Security/CWE-117/LogInjection.ql +query: Security/CWE-117/LogInjection.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/main.go b/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/main.go index 3eaacef9822a..5acaded1e7a0 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/main.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/main.go @@ -15,10 +15,10 @@ import ( type Greeter struct{} -func (g *Greeter) Hello(ctx context.Context, req *pb.Request, rsp *pb.Response) error { // $ serverRequest="definition of req" +func (g *Greeter) Hello(ctx context.Context, req *pb.Request, rsp *pb.Response) error { // $ serverRequest="definition of req" Source // var access name := req.Name - fmt.Println("Name :: %s", name) + fmt.Println("Name :: %s", name) // $ Alert return nil } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/CONSISTENCY/DataFlowConsistency.expected b/go/ql/test/library-tests/semmle/go/frameworks/Revel/CONSISTENCY/DataFlowConsistency.expected index 0fd726cd886a..999379f92981 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/CONSISTENCY/DataFlowConsistency.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/CONSISTENCY/DataFlowConsistency.expected @@ -1,28 +1,28 @@ reverseRead -| EndToEnd.go:30:35:30:35 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:30:35:30:42 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:36:18:36:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:36:18:36:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:44:18:44:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:44:18:44:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:51:20:51:20 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:51:20:51:27 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:58:18:58:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:58:18:58:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:64:26:64:26 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:64:26:64:33 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:69:22:69:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:69:22:69:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:74:22:74:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:74:22:74:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:79:35:79:35 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:79:35:79:42 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:84:22:84:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:84:22:84:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:89:21:89:21 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:89:21:89:28 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:94:20:94:20 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | -| EndToEnd.go:94:20:94:27 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:31:35:31:35 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:31:35:31:42 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:37:18:37:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:37:18:37:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:45:18:45:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:45:18:45:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:52:20:52:20 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:52:20:52:27 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:59:18:59:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:59:18:59:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:65:26:65:26 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:65:26:65:33 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:70:22:70:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:70:22:70:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:75:22:75:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:75:22:75:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:80:35:80:35 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:80:35:80:42 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:85:22:85:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:85:22:85:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:90:21:90:21 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:90:21:90:28 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:95:20:95:20 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | +| EndToEnd.go:95:20:95:27 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | Revel.go:26:7:26:7 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | Revel.go:27:7:27:7 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | Revel.go:27:7:27:14 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/EndToEnd.go b/go/ql/test/library-tests/semmle/go/frameworks/Revel/EndToEnd.go index 69fc2c52c4a2..0e60981e13d9 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/EndToEnd.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/EndToEnd.go @@ -3,10 +3,11 @@ package main import ( "bytes" "errors" - staticControllers "github.com/revel/modules/static/app/controllers" - "github.com/revel/revel" "os" "time" + + staticControllers "github.com/revel/modules/static/app/controllers" + "github.com/revel/revel" ) // Use typical inheritence pattern, per github.com/revel/examples/booking: @@ -33,8 +34,8 @@ func (c MyRoute) Handler1() revel.Result { func (c MyRoute) Handler2() revel.Result { // BAD: the RenderBinary function copies an `io.Reader` to the user's browser. buf := &bytes.Buffer{} - buf.WriteString(c.Params.Form.Get("someField")) - return c.RenderBinary(buf, "index.html", revel.Inline, time.Now()) // $ responsebody='buf' + buf.WriteString(c.Params.Form.Get("someField")) // $ Source[go/reflected-xss] + return c.RenderBinary(buf, "index.html", revel.Inline, time.Now()) // $ responsebody='buf' Alert[go/reflected-xss] } func (c MyRoute) Handler3() revel.Result { @@ -55,18 +56,18 @@ func (c MyRoute) Handler4() revel.Result { func (c MyRoute) Handler5() revel.Result { // BAD: returning an arbitrary file (but this is detected at the os.Open call, not // due to modelling Revel) - f, _ := os.Open(c.Params.Form.Get("someField")) + f, _ := os.Open(c.Params.Form.Get("someField")) // $ Alert[go/path-injection] return c.RenderFile(f, revel.Inline) } func (c MyRoute) Handler6() revel.Result { // BAD: returning an arbitrary file (detected as a user-controlled file-op, not XSS) - return c.RenderFileName(c.Params.Form.Get("someField"), revel.Inline) + return c.RenderFileName(c.Params.Form.Get("someField"), revel.Inline) // $ Alert[go/path-injection] } func (c MyRoute) Handler7() revel.Result { // BAD: straightforward XSS - return c.RenderHTML(c.Params.Form.Get("someField")) // $ responsebody='call to Get' + return c.RenderHTML(c.Params.Form.Get("someField")) // $ responsebody='call to Get' Alert[go/reflected-xss] } func (c MyRoute) Handler8() revel.Result { @@ -91,5 +92,5 @@ func (c MyRoute) Handler11() revel.Result { func (c MyRoute) Handler12() revel.Result { // BAD: open redirect - return c.Redirect(c.Params.Form.Get("someField")) + return c.Redirect(c.Params.Form.Get("someField")) // $ Alert[go/unvalidated-url-redirection] } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected b/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected index d3f52f4f9c67..3c889cd177cb 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected @@ -1,19 +1,19 @@ #select -| EndToEnd.go:94:20:94:49 | call to Get | EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:49 | call to Get | This path to an untrusted URL redirection depends on a $@. | EndToEnd.go:94:20:94:27 | selection of Params | user-provided value | +| EndToEnd.go:95:20:95:49 | call to Get | EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:49 | call to Get | This path to an untrusted URL redirection depends on a $@. | EndToEnd.go:95:20:95:27 | selection of Params | user-provided value | edges -| EndToEnd.go:94:20:94:27 | implicit dereference | EndToEnd.go:94:20:94:27 | selection of Params [postupdate] | provenance | Config | -| EndToEnd.go:94:20:94:27 | implicit dereference | EndToEnd.go:94:20:94:32 | selection of Form | provenance | Config | -| EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:27 | implicit dereference | provenance | Src:MaD:2 Config | -| EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:32 | selection of Form | provenance | Src:MaD:2 Config | -| EndToEnd.go:94:20:94:27 | selection of Params [postupdate] | EndToEnd.go:94:20:94:27 | implicit dereference | provenance | Config | -| EndToEnd.go:94:20:94:32 | selection of Form | EndToEnd.go:94:20:94:49 | call to Get | provenance | Config Sink:MaD:1 | +| EndToEnd.go:95:20:95:27 | implicit dereference | EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | provenance | Config | +| EndToEnd.go:95:20:95:27 | implicit dereference | EndToEnd.go:95:20:95:32 | selection of Form | provenance | Config | +| EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:27 | implicit dereference | provenance | Src:MaD:2 Config | +| EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:32 | selection of Form | provenance | Src:MaD:2 Config | +| EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | EndToEnd.go:95:20:95:27 | implicit dereference | provenance | Config | +| EndToEnd.go:95:20:95:32 | selection of Form | EndToEnd.go:95:20:95:49 | call to Get | provenance | Config Sink:MaD:1 | models | 1 | Sink: group:revel; Controller; true; Redirect; ; ; Argument[0]; url-redirection; manual | | 2 | Source: group:revel; Controller; true; Params; ; ; ; remote; manual | nodes -| EndToEnd.go:94:20:94:27 | implicit dereference | semmle.label | implicit dereference | -| EndToEnd.go:94:20:94:27 | selection of Params | semmle.label | selection of Params | -| EndToEnd.go:94:20:94:27 | selection of Params [postupdate] | semmle.label | selection of Params [postupdate] | -| EndToEnd.go:94:20:94:32 | selection of Form | semmle.label | selection of Form | -| EndToEnd.go:94:20:94:49 | call to Get | semmle.label | call to Get | +| EndToEnd.go:95:20:95:27 | implicit dereference | semmle.label | implicit dereference | +| EndToEnd.go:95:20:95:27 | selection of Params | semmle.label | selection of Params | +| EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | semmle.label | selection of Params [postupdate] | +| EndToEnd.go:95:20:95:32 | selection of Form | semmle.label | selection of Form | +| EndToEnd.go:95:20:95:49 | call to Get | semmle.label | call to Get | subpaths diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.qlref b/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.qlref index 867dd7665618..13add930f517 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.qlref +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.qlref @@ -1,2 +1,4 @@ query: Security/CWE-601/OpenUrlRedirect.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.expected b/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.expected index 9ea4016a7e47..0de532aa186d 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.expected @@ -1,16 +1,16 @@ #select -| EndToEnd.go:37:24:37:26 | buf | EndToEnd.go:36:18:36:25 | selection of Params | EndToEnd.go:37:24:37:26 | buf | Cross-site scripting vulnerability due to $@. | EndToEnd.go:36:18:36:25 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | | -| EndToEnd.go:69:22:69:51 | call to Get | EndToEnd.go:69:22:69:29 | selection of Params | EndToEnd.go:69:22:69:51 | call to Get | Cross-site scripting vulnerability due to $@. | EndToEnd.go:69:22:69:29 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | | +| EndToEnd.go:38:24:38:26 | buf | EndToEnd.go:37:18:37:25 | selection of Params | EndToEnd.go:38:24:38:26 | buf | Cross-site scripting vulnerability due to $@. | EndToEnd.go:37:18:37:25 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | | +| EndToEnd.go:70:22:70:51 | call to Get | EndToEnd.go:70:22:70:29 | selection of Params | EndToEnd.go:70:22:70:51 | call to Get | Cross-site scripting vulnerability due to $@. | EndToEnd.go:70:22:70:29 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | | | Revel.go:70:22:70:35 | selection of Query | Revel.go:70:22:70:29 | selection of Params | Revel.go:70:22:70:35 | selection of Query | Cross-site scripting vulnerability due to $@. The value is $@. | Revel.go:70:22:70:29 | selection of Params | user-provided value | views/myAppController/rawRead.html:1:1:2:9 | {{raw .Foo}}\n{{.Bar}}\n | instantiated as a raw template | | examples/booking/app/init.go:36:44:36:53 | selection of Path | examples/booking/app/init.go:36:44:36:48 | selection of URL | examples/booking/app/init.go:36:44:36:53 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:36:44:36:48 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | | | examples/booking/app/init.go:40:49:40:58 | selection of Path | examples/booking/app/init.go:40:49:40:53 | selection of URL | examples/booking/app/init.go:40:49:40:58 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:40:49:40:53 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | | edges -| EndToEnd.go:36:2:36:4 | buf [postupdate] | EndToEnd.go:37:24:37:26 | buf | provenance | | -| EndToEnd.go:36:18:36:25 | selection of Params | EndToEnd.go:36:18:36:30 | selection of Form | provenance | Src:MaD:1 | -| EndToEnd.go:36:18:36:30 | selection of Form | EndToEnd.go:36:18:36:47 | call to Get | provenance | MaD:4 | -| EndToEnd.go:36:18:36:47 | call to Get | EndToEnd.go:36:2:36:4 | buf [postupdate] | provenance | MaD:3 | -| EndToEnd.go:69:22:69:29 | selection of Params | EndToEnd.go:69:22:69:34 | selection of Form | provenance | Src:MaD:1 | -| EndToEnd.go:69:22:69:34 | selection of Form | EndToEnd.go:69:22:69:51 | call to Get | provenance | MaD:4 | +| EndToEnd.go:37:2:37:4 | buf [postupdate] | EndToEnd.go:38:24:38:26 | buf | provenance | | +| EndToEnd.go:37:18:37:25 | selection of Params | EndToEnd.go:37:18:37:30 | selection of Form | provenance | Src:MaD:1 | +| EndToEnd.go:37:18:37:30 | selection of Form | EndToEnd.go:37:18:37:47 | call to Get | provenance | MaD:4 | +| EndToEnd.go:37:18:37:47 | call to Get | EndToEnd.go:37:2:37:4 | buf [postupdate] | provenance | MaD:3 | +| EndToEnd.go:70:22:70:29 | selection of Params | EndToEnd.go:70:22:70:34 | selection of Form | provenance | Src:MaD:1 | +| EndToEnd.go:70:22:70:34 | selection of Form | EndToEnd.go:70:22:70:51 | call to Get | provenance | MaD:4 | | Revel.go:70:22:70:29 | selection of Params | Revel.go:70:22:70:35 | selection of Query | provenance | Src:MaD:1 | | examples/booking/app/init.go:36:44:36:48 | selection of URL | examples/booking/app/init.go:36:44:36:53 | selection of Path | provenance | Src:MaD:2 | | examples/booking/app/init.go:40:49:40:53 | selection of URL | examples/booking/app/init.go:40:49:40:58 | selection of Path | provenance | Src:MaD:2 | @@ -20,14 +20,14 @@ models | 3 | Summary: io; StringWriter; true; WriteString; ; ; Argument[0]; Argument[receiver]; taint; manual | | 4 | Summary: net/url; Values; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual | nodes -| EndToEnd.go:36:2:36:4 | buf [postupdate] | semmle.label | buf [postupdate] | -| EndToEnd.go:36:18:36:25 | selection of Params | semmle.label | selection of Params | -| EndToEnd.go:36:18:36:30 | selection of Form | semmle.label | selection of Form | -| EndToEnd.go:36:18:36:47 | call to Get | semmle.label | call to Get | -| EndToEnd.go:37:24:37:26 | buf | semmle.label | buf | -| EndToEnd.go:69:22:69:29 | selection of Params | semmle.label | selection of Params | -| EndToEnd.go:69:22:69:34 | selection of Form | semmle.label | selection of Form | -| EndToEnd.go:69:22:69:51 | call to Get | semmle.label | call to Get | +| EndToEnd.go:37:2:37:4 | buf [postupdate] | semmle.label | buf [postupdate] | +| EndToEnd.go:37:18:37:25 | selection of Params | semmle.label | selection of Params | +| EndToEnd.go:37:18:37:30 | selection of Form | semmle.label | selection of Form | +| EndToEnd.go:37:18:37:47 | call to Get | semmle.label | call to Get | +| EndToEnd.go:38:24:38:26 | buf | semmle.label | buf | +| EndToEnd.go:70:22:70:29 | selection of Params | semmle.label | selection of Params | +| EndToEnd.go:70:22:70:34 | selection of Form | semmle.label | selection of Form | +| EndToEnd.go:70:22:70:51 | call to Get | semmle.label | call to Get | | Revel.go:70:22:70:29 | selection of Params | semmle.label | selection of Params | | Revel.go:70:22:70:35 | selection of Query | semmle.label | selection of Query | | examples/booking/app/init.go:36:44:36:48 | selection of URL | semmle.label | selection of URL | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.qlref b/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.qlref index 754513d72bb3..e6b791f39fca 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.qlref +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.qlref @@ -1,2 +1,4 @@ query: Security/CWE-079/ReflectedXss.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/Revel.go b/go/ql/test/library-tests/semmle/go/frameworks/Revel/Revel.go index f09dcd6fa586..219e1dddb4c9 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/Revel.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/Revel.go @@ -67,7 +67,7 @@ func (c myAppController) accessingParamsJSONIsUnsafe() { func (c myAppController) rawRead() { // $ responsebody='argument corresponding to c' c.ViewArgs["Foo"] = "

raw HTML

" // $ responsebody='"

raw HTML

"' c.ViewArgs["Bar"] = "

not raw HTML

" - c.ViewArgs["Foo"] = c.Params.Query // $ responsebody='selection of Query' + c.ViewArgs["Foo"] = c.Params.Query // $ responsebody='selection of Query' Alert[go/reflected-xss] c.Render() } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.expected b/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.expected index 7337f636c477..e007da1c95d7 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.expected @@ -1,21 +1,21 @@ #select -| EndToEnd.go:58:18:58:47 | call to Get | EndToEnd.go:58:18:58:25 | selection of Params | EndToEnd.go:58:18:58:47 | call to Get | This path depends on a $@. | EndToEnd.go:58:18:58:25 | selection of Params | user-provided value | -| EndToEnd.go:64:26:64:55 | call to Get | EndToEnd.go:64:26:64:33 | selection of Params | EndToEnd.go:64:26:64:55 | call to Get | This path depends on a $@. | EndToEnd.go:64:26:64:33 | selection of Params | user-provided value | +| EndToEnd.go:59:18:59:47 | call to Get | EndToEnd.go:59:18:59:25 | selection of Params | EndToEnd.go:59:18:59:47 | call to Get | This path depends on a $@. | EndToEnd.go:59:18:59:25 | selection of Params | user-provided value | +| EndToEnd.go:65:26:65:55 | call to Get | EndToEnd.go:65:26:65:33 | selection of Params | EndToEnd.go:65:26:65:55 | call to Get | This path depends on a $@. | EndToEnd.go:65:26:65:33 | selection of Params | user-provided value | edges -| EndToEnd.go:58:18:58:25 | selection of Params | EndToEnd.go:58:18:58:30 | selection of Form | provenance | Src:MaD:3 | -| EndToEnd.go:58:18:58:30 | selection of Form | EndToEnd.go:58:18:58:47 | call to Get | provenance | MaD:4 Sink:MaD:2 | -| EndToEnd.go:64:26:64:33 | selection of Params | EndToEnd.go:64:26:64:38 | selection of Form | provenance | Src:MaD:3 | -| EndToEnd.go:64:26:64:38 | selection of Form | EndToEnd.go:64:26:64:55 | call to Get | provenance | MaD:4 Sink:MaD:1 | +| EndToEnd.go:59:18:59:25 | selection of Params | EndToEnd.go:59:18:59:30 | selection of Form | provenance | Src:MaD:3 | +| EndToEnd.go:59:18:59:30 | selection of Form | EndToEnd.go:59:18:59:47 | call to Get | provenance | MaD:4 Sink:MaD:2 | +| EndToEnd.go:65:26:65:33 | selection of Params | EndToEnd.go:65:26:65:38 | selection of Form | provenance | Src:MaD:3 | +| EndToEnd.go:65:26:65:38 | selection of Form | EndToEnd.go:65:26:65:55 | call to Get | provenance | MaD:4 Sink:MaD:1 | models | 1 | Sink: group:revel; Controller; true; RenderFileName; ; ; Argument[0]; path-injection; manual | | 2 | Sink: os; ; false; Open; ; ; Argument[0]; path-injection; manual | | 3 | Source: group:revel; Controller; true; Params; ; ; ; remote; manual | | 4 | Summary: net/url; Values; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual | nodes -| EndToEnd.go:58:18:58:25 | selection of Params | semmle.label | selection of Params | -| EndToEnd.go:58:18:58:30 | selection of Form | semmle.label | selection of Form | -| EndToEnd.go:58:18:58:47 | call to Get | semmle.label | call to Get | -| EndToEnd.go:64:26:64:33 | selection of Params | semmle.label | selection of Params | -| EndToEnd.go:64:26:64:38 | selection of Form | semmle.label | selection of Form | -| EndToEnd.go:64:26:64:55 | call to Get | semmle.label | call to Get | +| EndToEnd.go:59:18:59:25 | selection of Params | semmle.label | selection of Params | +| EndToEnd.go:59:18:59:30 | selection of Form | semmle.label | selection of Form | +| EndToEnd.go:59:18:59:47 | call to Get | semmle.label | call to Get | +| EndToEnd.go:65:26:65:33 | selection of Params | semmle.label | selection of Params | +| EndToEnd.go:65:26:65:38 | selection of Form | semmle.label | selection of Form | +| EndToEnd.go:65:26:65:55 | call to Get | semmle.label | call to Get | subpaths diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.qlref b/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.qlref index 78ce25b1921f..6eb2e94892f2 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.qlref +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.qlref @@ -1,2 +1,4 @@ query: Security/CWE-022/TaintedPath.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/examples/booking/app/init.go b/go/ql/test/library-tests/semmle/go/frameworks/Revel/examples/booking/app/init.go index 2f7fef73fc29..ca9232ec7c79 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/examples/booking/app/init.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/examples/booking/app/init.go @@ -33,11 +33,11 @@ func init() { switch event { case revel.ENGINE_BEFORE_INITIALIZED: revel.AddHTTPMux("/this/is/a/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintln(w, "Hi there, it worked", r.URL.Path) // $ responsebody='selection of Path' responsebody='"Hi there, it worked"' + fmt.Fprintln(w, "Hi there, it worked", r.URL.Path) // $ responsebody='selection of Path' responsebody='"Hi there, it worked"' Alert[go/reflected-xss] w.WriteHeader(200) })) revel.AddHTTPMux("/this/is/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintln(w, "Hi there, shorter prefix", r.URL.Path) // $ responsebody='selection of Path' responsebody='"Hi there, shorter prefix"' + fmt.Fprintln(w, "Hi there, shorter prefix", r.URL.Path) // $ responsebody='selection of Path' responsebody='"Hi there, shorter prefix"' Alert[go/reflected-xss] w.WriteHeader(200) })) } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/ReflectedXss.qlref b/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/ReflectedXss.qlref index 754513d72bb3..e6b791f39fca 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/ReflectedXss.qlref +++ b/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/ReflectedXss.qlref @@ -1,2 +1,4 @@ query: Security/CWE-079/ReflectedXss.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/SqlInjection.qlref b/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/SqlInjection.qlref index b6916bd2cd46..e19181577447 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/SqlInjection.qlref +++ b/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/SqlInjection.qlref @@ -1,2 +1,4 @@ query: Security/CWE-089/SqlInjection.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/test.go b/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/test.go index a89167e126c4..6b8a02a1fb3b 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/test.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/test.go @@ -9,50 +9,50 @@ import ( func test(request *http.Request, writer http.ResponseWriter) { - param1 := request.URL.Query().Get("param1") + param1 := request.URL.Query().Get("param1") // $ Source[go/reflected-xss] writer.Write([]byte(html.EscapeString(param1))) // GOOD: escaped. - writer.Write([]byte(html.UnescapeString(param1))) // BAD: unescaped. + writer.Write([]byte(html.UnescapeString(param1))) // $ Alert[go/reflected-xss] // BAD: unescaped. - node, _ := html.Parse(request.Body) - writer.Write([]byte(node.Data)) // BAD: writing unescaped HTML data + node, _ := html.Parse(request.Body) // $ Source[go/reflected-xss] + writer.Write([]byte(node.Data)) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data - node2, _ := html.ParseWithOptions(request.Body) - writer.Write([]byte(node2.Data)) // BAD: writing unescaped HTML data + node2, _ := html.ParseWithOptions(request.Body) // $ Source[go/reflected-xss] + writer.Write([]byte(node2.Data)) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data - nodes, _ := html.ParseFragment(request.Body, nil) - writer.Write([]byte(nodes[0].Data)) // BAD: writing unescaped HTML data + nodes, _ := html.ParseFragment(request.Body, nil) // $ Source[go/reflected-xss] + writer.Write([]byte(nodes[0].Data)) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data - nodes2, _ := html.ParseFragmentWithOptions(request.Body, nil) - writer.Write([]byte(nodes2[0].Data)) // BAD: writing unescaped HTML data + nodes2, _ := html.ParseFragmentWithOptions(request.Body, nil) // $ Source[go/reflected-xss] + writer.Write([]byte(nodes2[0].Data)) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data - html.Render(writer, node) // BAD: rendering untrusted HTML to `writer` + html.Render(writer, node) // $ Alert[go/reflected-xss] // BAD: rendering untrusted HTML to `writer` - tokenizer := html.NewTokenizer(request.Body) - writer.Write(tokenizer.Buffered()) // BAD: writing unescaped HTML data - writer.Write(tokenizer.Raw()) // BAD: writing unescaped HTML data + tokenizer := html.NewTokenizer(request.Body) // $ Source[go/reflected-xss] + writer.Write(tokenizer.Buffered()) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data + writer.Write(tokenizer.Raw()) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data _, value, _ := tokenizer.TagAttr() - writer.Write(value) // BAD: writing unescaped HTML data - writer.Write(tokenizer.Text()) // BAD: writing unescaped HTML data - writer.Write([]byte(tokenizer.Token().Data)) // BAD: writing unescaped HTML data + writer.Write(value) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data + writer.Write(tokenizer.Text()) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data + writer.Write([]byte(tokenizer.Token().Data)) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data - tokenizerFragment := html.NewTokenizerFragment(request.Body, "some context") - writer.Write(tokenizerFragment.Buffered()) // BAD: writing unescaped HTML data + tokenizerFragment := html.NewTokenizerFragment(request.Body, "some context") // $ Source[go/reflected-xss] + writer.Write(tokenizerFragment.Buffered()) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data var cleanNode html.Node - taintedNode, _ := html.Parse(request.Body) + taintedNode, _ := html.Parse(request.Body) // $ Source[go/reflected-xss] cleanNode.AppendChild(taintedNode) - html.Render(writer, &cleanNode) // BAD: writing unescaped HTML data + html.Render(writer, &cleanNode) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data var cleanNode2 html.Node - taintedNode2, _ := html.Parse(request.Body) + taintedNode2, _ := html.Parse(request.Body) // $ Source[go/reflected-xss] cleanNode2.InsertBefore(taintedNode2, &cleanNode2) - html.Render(writer, &cleanNode2) // BAD: writing unescaped HTML data + html.Render(writer, &cleanNode2) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data } func sqlTest(request *http.Request, db *sql.DB) { // Ensure EscapeString is a taint propagator for non-XSS queries, e.g. SQL injection: - cookie, _ := request.Cookie("SomeCookie") - db.Query(html.EscapeString(cookie.Value)) + cookie, _ := request.Cookie("SomeCookie") // $ Source[go/sql-injection] + db.Query(html.EscapeString(cookie.Value)) // $ Alert[go/sql-injection] } diff --git a/go/ql/test/query-tests/InconsistentCode/ConstantLengthComparison/ConstantLengthComparison.go b/go/ql/test/query-tests/InconsistentCode/ConstantLengthComparison/ConstantLengthComparison.go index cec41e2dab2d..a1a6b1f309ed 100644 --- a/go/ql/test/query-tests/InconsistentCode/ConstantLengthComparison/ConstantLengthComparison.go +++ b/go/ql/test/query-tests/InconsistentCode/ConstantLengthComparison/ConstantLengthComparison.go @@ -2,7 +2,7 @@ package main func isPrefixOf(xs, ys []int) bool { for i := 0; i < len(xs); i++ { - if len(ys) == 0 || xs[i] != ys[i] { // NOT OK + if len(ys) == 0 || xs[i] != ys[i] { // $ Alert // NOT OK return false } } diff --git a/go/ql/test/query-tests/InconsistentCode/ConstantLengthComparison/ConstantLengthComparison.qlref b/go/ql/test/query-tests/InconsistentCode/ConstantLengthComparison/ConstantLengthComparison.qlref index 315838df15f7..edd5d2d1d433 100644 --- a/go/ql/test/query-tests/InconsistentCode/ConstantLengthComparison/ConstantLengthComparison.qlref +++ b/go/ql/test/query-tests/InconsistentCode/ConstantLengthComparison/ConstantLengthComparison.qlref @@ -1 +1,2 @@ -InconsistentCode/ConstantLengthComparison.ql +query: InconsistentCode/ConstantLengthComparison.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/InconsistentCode/InconsistentLoopOrientation/InconsistentLoopOrientation.go b/go/ql/test/query-tests/InconsistentCode/InconsistentLoopOrientation/InconsistentLoopOrientation.go index 077015ced99d..cda530aec6a7 100644 --- a/go/ql/test/query-tests/InconsistentCode/InconsistentLoopOrientation/InconsistentLoopOrientation.go +++ b/go/ql/test/query-tests/InconsistentCode/InconsistentLoopOrientation/InconsistentLoopOrientation.go @@ -7,7 +7,7 @@ func zeroOutExceptBad(a []int, lower int, upper int) { } // zero out everything above index `upper` - for i := upper + 1; i < len(a); i-- { // NOT OK + for i := upper + 1; i < len(a); i-- { // $ Alert // NOT OK a[i] = 0 } } diff --git a/go/ql/test/query-tests/InconsistentCode/InconsistentLoopOrientation/InconsistentLoopOrientation.qlref b/go/ql/test/query-tests/InconsistentCode/InconsistentLoopOrientation/InconsistentLoopOrientation.qlref index 62ab35e22578..336261fde233 100644 --- a/go/ql/test/query-tests/InconsistentCode/InconsistentLoopOrientation/InconsistentLoopOrientation.qlref +++ b/go/ql/test/query-tests/InconsistentCode/InconsistentLoopOrientation/InconsistentLoopOrientation.qlref @@ -1 +1,2 @@ -InconsistentCode/InconsistentLoopOrientation.ql +query: InconsistentCode/InconsistentLoopOrientation.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/InconsistentCode/InconsistentLoopOrientation/main.go b/go/ql/test/query-tests/InconsistentCode/InconsistentLoopOrientation/main.go index ede1c5878fba..4cb6e1feac7c 100644 --- a/go/ql/test/query-tests/InconsistentCode/InconsistentLoopOrientation/main.go +++ b/go/ql/test/query-tests/InconsistentCode/InconsistentLoopOrientation/main.go @@ -6,12 +6,12 @@ func f1(i int) { } func f2(i int, s string) { - for j := i + 1; j < len(s); j-- { // NOT OK + for j := i + 1; j < len(s); j-- { // $ Alert // NOT OK } } func f3(s string) { - for i, l := 0, len(s); i > l; i++ { // NOT OK + for i, l := 0, len(s); i > l; i++ { // $ Alert // NOT OK } } @@ -22,7 +22,7 @@ func f4(lower int, a []int) { } func f5(upper int, a []int) { - for i := upper + 1; i < len(a); i-- { // NOT OK + for i := upper + 1; i < len(a); i-- { // $ Alert // NOT OK a[i] = 0 } } diff --git a/go/ql/test/query-tests/InconsistentCode/LengthComparisonOffByOne/LengthComparisonOffByOne.go b/go/ql/test/query-tests/InconsistentCode/LengthComparisonOffByOne/LengthComparisonOffByOne.go index 7db63c62bfe0..965178e2cdcd 100644 --- a/go/ql/test/query-tests/InconsistentCode/LengthComparisonOffByOne/LengthComparisonOffByOne.go +++ b/go/ql/test/query-tests/InconsistentCode/LengthComparisonOffByOne/LengthComparisonOffByOne.go @@ -5,9 +5,9 @@ import "strings" func containsBad(searchName string, names string) bool { values := strings.Split(names, ",") // BAD: index could be equal to length - for i := 0; i <= len(values); i++ { + for i := 0; i <= len(values); i++ { // $ Alert // When i = length, this access will be out of bounds - if values[i] == searchName { + if values[i] == searchName { // $ Source return true } } diff --git a/go/ql/test/query-tests/InconsistentCode/LengthComparisonOffByOne/LengthComparisonOffByOne.qlref b/go/ql/test/query-tests/InconsistentCode/LengthComparisonOffByOne/LengthComparisonOffByOne.qlref index 8692ba8a17da..ddd036de50a3 100644 --- a/go/ql/test/query-tests/InconsistentCode/LengthComparisonOffByOne/LengthComparisonOffByOne.qlref +++ b/go/ql/test/query-tests/InconsistentCode/LengthComparisonOffByOne/LengthComparisonOffByOne.qlref @@ -1 +1,2 @@ -InconsistentCode/LengthComparisonOffByOne.ql +query: InconsistentCode/LengthComparisonOffByOne.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/InconsistentCode/LengthComparisonOffByOne/main.go b/go/ql/test/query-tests/InconsistentCode/LengthComparisonOffByOne/main.go index 3a426dc554da..01e849c0f2fc 100644 --- a/go/ql/test/query-tests/InconsistentCode/LengthComparisonOffByOne/main.go +++ b/go/ql/test/query-tests/InconsistentCode/LengthComparisonOffByOne/main.go @@ -3,8 +3,8 @@ package main import "regexp" func f1(i int, a []int) int { - if i <= len(a) { // NOT OK - return a[i] + if i <= len(a) { // $ Alert // NOT OK + return a[i] // $ Source } return -1 } @@ -26,8 +26,8 @@ func f3(i int, a []int) int { } func f4(i int, a []int) int { - if len(a) > 0 { // NOT OK - return a[1] + if len(a) > 0 { // $ Alert // NOT OK + return a[1] // $ Source } return -1 } diff --git a/go/ql/test/query-tests/InconsistentCode/MissingErrorCheck/MissingErrorCheck.qlref b/go/ql/test/query-tests/InconsistentCode/MissingErrorCheck/MissingErrorCheck.qlref index 519bdd54e687..c70c6a57526a 100644 --- a/go/ql/test/query-tests/InconsistentCode/MissingErrorCheck/MissingErrorCheck.qlref +++ b/go/ql/test/query-tests/InconsistentCode/MissingErrorCheck/MissingErrorCheck.qlref @@ -1 +1,2 @@ -InconsistentCode/MissingErrorCheck.ql +query: InconsistentCode/MissingErrorCheck.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/InconsistentCode/MissingErrorCheck/tests.go b/go/ql/test/query-tests/InconsistentCode/MissingErrorCheck/tests.go index da60b272bbe2..1f45bbbf4e27 100644 --- a/go/ql/test/query-tests/InconsistentCode/MissingErrorCheck/tests.go +++ b/go/ql/test/query-tests/InconsistentCode/MissingErrorCheck/tests.go @@ -58,7 +58,7 @@ func missingCheckMayFail(fname string) { result, err := os.Open(fname) - fmt.Printf("Opened: %v\n", *result) // NOT OK + fmt.Printf("Opened: %v\n", *result) // $ Alert // NOT OK fmt.Printf("%v\n", err) // use err } @@ -240,7 +240,7 @@ func mishandlesMyError(input int) { result, err := returnsMyError(input) - fmt.Printf("Got: %d\n", *result) // NOT OK + fmt.Printf("Got: %d\n", *result) // $ Alert // NOT OK fmt.Printf("%v\n", err) // use err } diff --git a/go/ql/test/query-tests/InconsistentCode/MistypedExponentiation/MistypedExponentiation.go b/go/ql/test/query-tests/InconsistentCode/MistypedExponentiation/MistypedExponentiation.go index f6e3108f581b..0ae2c8a0afb6 100644 --- a/go/ql/test/query-tests/InconsistentCode/MistypedExponentiation/MistypedExponentiation.go +++ b/go/ql/test/query-tests/InconsistentCode/MistypedExponentiation/MistypedExponentiation.go @@ -3,5 +3,5 @@ package main import "fmt" func test() { - fmt.Println(2 ^ 32) // should be 1 << 32 + fmt.Println(2 ^ 32) // $ Alert // should be 1 << 32 } diff --git a/go/ql/test/query-tests/InconsistentCode/MistypedExponentiation/MistypedExponentiation.qlref b/go/ql/test/query-tests/InconsistentCode/MistypedExponentiation/MistypedExponentiation.qlref index bd96eb93eb49..40b505ceca23 100644 --- a/go/ql/test/query-tests/InconsistentCode/MistypedExponentiation/MistypedExponentiation.qlref +++ b/go/ql/test/query-tests/InconsistentCode/MistypedExponentiation/MistypedExponentiation.qlref @@ -1 +1,2 @@ -InconsistentCode/MistypedExponentiation.ql +query: InconsistentCode/MistypedExponentiation.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/InconsistentCode/MistypedExponentiation/main.go b/go/ql/test/query-tests/InconsistentCode/MistypedExponentiation/main.go index b8b4be44847e..5aa436eb08f3 100644 --- a/go/ql/test/query-tests/InconsistentCode/MistypedExponentiation/main.go +++ b/go/ql/test/query-tests/InconsistentCode/MistypedExponentiation/main.go @@ -12,13 +12,13 @@ func main() { expectingResponse := 1 << 5 power := 10 - fmt.Println(3 ^ 5) // Not OK + fmt.Println(3 ^ 5) // $ Alert // Not OK fmt.Println(0755 ^ 2423) // OK - fmt.Println(2 ^ 32) // Not OK - fmt.Println(10 ^ 5) // Not OK - fmt.Println(10 ^ exp) // Not OK + fmt.Println(2 ^ 32) // $ Alert // Not OK + fmt.Println(10 ^ 5) // $ Alert // Not OK + fmt.Println(10 ^ exp) // $ Alert // Not OK fmt.Println(253 ^ expectingResponse) // OK - fmt.Println(2 ^ power) // Not OK + fmt.Println(2 ^ power) // $ Alert // Not OK mask := (((1 << 10) - 1) ^ 7) // OK diff --git a/go/ql/test/query-tests/InconsistentCode/WhitespaceContradictsPrecedence/WhitespaceContradictsPrecedence.go b/go/ql/test/query-tests/InconsistentCode/WhitespaceContradictsPrecedence/WhitespaceContradictsPrecedence.go index ee6987ec9312..bee4b5921b0f 100644 --- a/go/ql/test/query-tests/InconsistentCode/WhitespaceContradictsPrecedence/WhitespaceContradictsPrecedence.go +++ b/go/ql/test/query-tests/InconsistentCode/WhitespaceContradictsPrecedence/WhitespaceContradictsPrecedence.go @@ -3,5 +3,5 @@ package main // autoformat-ignore (otherwise gofmt will fix the spacing to reflect precedence) func isBitSetBad(x int, pos uint) bool { - return x & 1<> 1; + return x+x >> 1; // $ Alert } func ok3(x int) int { diff --git a/go/ql/test/query-tests/InconsistentCode/WrappedErrorAlwaysNil/WrappedErrorAlwaysNil.go b/go/ql/test/query-tests/InconsistentCode/WrappedErrorAlwaysNil/WrappedErrorAlwaysNil.go index 70ccce77ba74..d5901800cbbf 100644 --- a/go/ql/test/query-tests/InconsistentCode/WrappedErrorAlwaysNil/WrappedErrorAlwaysNil.go +++ b/go/ql/test/query-tests/InconsistentCode/WrappedErrorAlwaysNil/WrappedErrorAlwaysNil.go @@ -28,7 +28,7 @@ func test1(input string) error { } if ok2, _ := f2(input); !ok2 { // BAD: Wrapped error is always nil - return errors.Wrap(err, "") + return errors.Wrap(err, "") // $ Alert } return nil } @@ -38,13 +38,13 @@ func test2(err error) { errors.Wrap(err, "") // BAD: Wrapped error is always nil - errors.Wrap(nil, "") + errors.Wrap(nil, "") // $ Alert err = nil // BAD: Wrapped error is always nil - errors.Wrap(err, "") + errors.Wrap(err, "") // $ Alert var localErr error = nil // BAD: Wrapped error is always nil - errors.Wrap(localErr, "") + errors.Wrap(localErr, "") // $ Alert } diff --git a/go/ql/test/query-tests/InconsistentCode/WrappedErrorAlwaysNil/WrappedErrorAlwaysNil.qlref b/go/ql/test/query-tests/InconsistentCode/WrappedErrorAlwaysNil/WrappedErrorAlwaysNil.qlref index bad618814a12..03f9d3ebda16 100644 --- a/go/ql/test/query-tests/InconsistentCode/WrappedErrorAlwaysNil/WrappedErrorAlwaysNil.qlref +++ b/go/ql/test/query-tests/InconsistentCode/WrappedErrorAlwaysNil/WrappedErrorAlwaysNil.qlref @@ -1 +1,2 @@ -InconsistentCode/WrappedErrorAlwaysNil.ql +query: InconsistentCode/WrappedErrorAlwaysNil.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/CompareIdenticalValues.go b/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/CompareIdenticalValues.go index b096cdf5ceca..594d8cfcca1a 100644 --- a/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/CompareIdenticalValues.go +++ b/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/CompareIdenticalValues.go @@ -6,7 +6,7 @@ type Rectangle struct { func (r *Rectangle) containsBad(x, y int) bool { return r.x <= x && - y <= y && // NOT OK + y <= y && // $ Alert // NOT OK x <= r.x+r.width && y <= r.y+r.height } diff --git a/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/CompareIdenticalValues.qlref b/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/CompareIdenticalValues.qlref index 7c3ac7ace2b4..e9d5bb357fdf 100644 --- a/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/CompareIdenticalValues.qlref +++ b/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/CompareIdenticalValues.qlref @@ -1 +1,2 @@ -RedundantCode/CompareIdenticalValues.ql +query: RedundantCode/CompareIdenticalValues.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/tst.go b/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/tst.go index 935e71bab996..fbe842b669ca 100644 --- a/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/tst.go +++ b/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/tst.go @@ -3,7 +3,7 @@ package main import "fmt" func foo(x int) bool { - return x == x // NOT OK + return x == x // $ Alert // NOT OK } func isNaN(x float32) bool { @@ -57,5 +57,5 @@ func baz2() bool { func baz3() bool { var y counter y.bimp() - return y == 0 // NOT OK + return y == 0 // $ Alert // NOT OK } diff --git a/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/vp.go b/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/vp.go index 64e070e660e6..9087a5895003 100644 --- a/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/vp.go +++ b/go/ql/test/query-tests/RedundantCode/CompareIdenticalValues/vp.go @@ -13,5 +13,5 @@ type t struct { } func (x *t) foo(other t) bool { - return x.GetLength() != x.GetLength() + return x.GetLength() != x.GetLength() // $ Alert } diff --git a/go/ql/test/query-tests/RedundantCode/DeadStoreOfField/DeadStoreOfField.go b/go/ql/test/query-tests/RedundantCode/DeadStoreOfField/DeadStoreOfField.go index b74b7312a7fe..7e1328e5a33f 100644 --- a/go/ql/test/query-tests/RedundantCode/DeadStoreOfField/DeadStoreOfField.go +++ b/go/ql/test/query-tests/RedundantCode/DeadStoreOfField/DeadStoreOfField.go @@ -5,5 +5,5 @@ type counter struct { } func (w counter) reset() { - w.val = 0 // NOT OK + w.val = 0 // $ Alert // NOT OK } diff --git a/go/ql/test/query-tests/RedundantCode/DeadStoreOfField/DeadStoreOfField.qlref b/go/ql/test/query-tests/RedundantCode/DeadStoreOfField/DeadStoreOfField.qlref index 90aa8beb7ad9..1fa9500a954b 100644 --- a/go/ql/test/query-tests/RedundantCode/DeadStoreOfField/DeadStoreOfField.qlref +++ b/go/ql/test/query-tests/RedundantCode/DeadStoreOfField/DeadStoreOfField.qlref @@ -1 +1,2 @@ -RedundantCode/DeadStoreOfField.ql +query: RedundantCode/DeadStoreOfField.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/DeadStoreOfLocal.qlref b/go/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/DeadStoreOfLocal.qlref index 9acb5d81615f..5e4405270c01 100644 --- a/go/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/DeadStoreOfLocal.qlref +++ b/go/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/DeadStoreOfLocal.qlref @@ -1 +1,2 @@ -RedundantCode/DeadStoreOfLocal.ql +query: RedundantCode/DeadStoreOfLocal.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/main.go b/go/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/main.go index 31062a18f984..ee7b9214a66b 100644 --- a/go/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/main.go +++ b/go/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/main.go @@ -22,7 +22,7 @@ func main() { } func deadParameter(x int) bool { // we don't want to flag x here - x = deadStore() // but we do want to flag this + x = deadStore() // $ Alert // but we do want to flag this return true } diff --git a/go/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/testdata.go b/go/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/testdata.go index dad31ebd1aef..da7d6db82c34 100644 --- a/go/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/testdata.go +++ b/go/ql/test/query-tests/RedundantCode/DeadStoreOfLocal/testdata.go @@ -29,12 +29,12 @@ func _() { func _() { var x int _ = x - x = deadStore() // BAD + x = deadStore() // $ Alert // BAD } func _() { var x int - x = deadStore() // BAD + x = deadStore() // $ Alert // BAD x = 0 _ = x } @@ -58,13 +58,13 @@ func _() { } func _() { - x := deadStore2() // BAD + x := deadStore2() // $ Alert // BAD x = "def" _ = x } func _() { - x := deadStore() // BAD + x := deadStore() // $ Alert // BAD x = 0 _ = x } @@ -96,18 +96,18 @@ func _() { } func _() { - x := deadStore() // BAD + x := deadStore() // $ Alert // BAD if b { - x = deadStore() // BAD + x = deadStore() // $ Alert // BAD } x = 0 _ = x } func _() { - x := deadStore() // BAD + x := deadStore() // $ Alert // BAD for b { - x = deadStore() // BAD + x = deadStore() // $ Alert // BAD } x = 0 _ = x @@ -125,13 +125,13 @@ func _() { } func _() { - x := deadStore() // BAD + x := deadStore() // $ Alert // BAD if b { - x = deadStore() // BAD - x = deadStore() // BAD + x = deadStore() // $ Alert // BAD + x = deadStore() // $ Alert // BAD } if b { - x = deadStore() // BAD + x = deadStore() // $ Alert // BAD } x = 0 _ = x @@ -140,7 +140,7 @@ func _() { func _() { x := 0 if b { - x = deadStore() // BAD + x = deadStore() // $ Alert // BAD x = 0 } if b { @@ -161,7 +161,7 @@ func _() { x := 0 for { _ = x - x = deadStore() // BAD + x = deadStore() // $ Alert // BAD x = 0 } } @@ -169,7 +169,7 @@ func _() { func _() { x := 0 for { - x += deadStore() // BAD + x += deadStore() // $ Alert // BAD x = 0 } } @@ -177,7 +177,7 @@ func _() { func _() { x := 0 for { - x++ // BAD + x++ // $ Alert // BAD x = 0 } } @@ -198,7 +198,7 @@ func _() { func _() { x := struct{ f int }{42} _ = x.f - x = struct{ f int }{23} + x = struct{ f int }{23} // $ Alert } func _() { @@ -259,13 +259,13 @@ func _() (x int) { } func _() (x int) { - x = deadStore() // BAD + x = deadStore() // $ Alert // BAD x = 0 return } func _() (x int) { - x = deadStore() // BAD + x = deadStore() // $ Alert // BAD return 0 } @@ -306,7 +306,7 @@ func _(a float32, b float32) (x int) { func _(a float32, b float32) (x int) { x = 1 - a /= b + a /= b // $ Alert return 2 } @@ -318,7 +318,7 @@ func _(a int, b int) (x int) { func _(a int, b int) (x int) { x = 1 - a %= b + a %= b // $ Alert return 2 } @@ -384,7 +384,7 @@ func _() { case true: _ = x default: - x = deadStore() // BAD + x = deadStore() // $ Alert // BAD fallthrough case b: } @@ -429,16 +429,16 @@ func _() { var ch chan int select { case ch <- 0: - x = deadStore() // BAD + x = deadStore() // $ Alert // BAD case <-ch: - x = deadStore() // BAD + x = deadStore() // $ Alert // BAD default: _ = x } } func _() { - x := deadStore() // BAD + x := deadStore() // $ Alert // BAD var ch chan int select { case ch <- 0: @@ -485,7 +485,7 @@ func _() { func _() { var x int if b { - x = deadStore() // BAD + x = deadStore() // $ Alert // BAD } if x = 0; b { @@ -539,7 +539,7 @@ func _() { func _() { x := 0 for x < 0 { - x = deadStore() // BAD + x = deadStore() // $ Alert // BAD if b { break } @@ -577,7 +577,7 @@ func _() { var x int for { if b { - x = deadStore() // BAD + x = deadStore() // $ Alert // BAD break } _ = x @@ -626,7 +626,7 @@ func _(v1, v2 int32) (int32, int32) { func _(v1, v2 int32) (int32, int32) { if v1 > v2 { - v1, _ = v2, v1 + v1, _ = v2, v1 // $ Alert } v1, v2 = 0, 0 return v1, v2 diff --git a/go/ql/test/query-tests/RedundantCode/DuplicateBranches/DuplicateBranches.go b/go/ql/test/query-tests/RedundantCode/DuplicateBranches/DuplicateBranches.go index f4bc36b63fe6..1f163c2867f9 100644 --- a/go/ql/test/query-tests/RedundantCode/DuplicateBranches/DuplicateBranches.go +++ b/go/ql/test/query-tests/RedundantCode/DuplicateBranches/DuplicateBranches.go @@ -1,7 +1,7 @@ package main func abs(x int) int { - if x >= 0 { + if x >= 0 { // $ Alert return x } else { return x diff --git a/go/ql/test/query-tests/RedundantCode/DuplicateBranches/DuplicateBranches.qlref b/go/ql/test/query-tests/RedundantCode/DuplicateBranches/DuplicateBranches.qlref index 3eb10d9d91fb..a32bc6c31f1a 100644 --- a/go/ql/test/query-tests/RedundantCode/DuplicateBranches/DuplicateBranches.qlref +++ b/go/ql/test/query-tests/RedundantCode/DuplicateBranches/DuplicateBranches.qlref @@ -1 +1,2 @@ -RedundantCode/DuplicateBranches.ql +query: RedundantCode/DuplicateBranches.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/RedundantCode/DuplicateBranches/main.go b/go/ql/test/query-tests/RedundantCode/DuplicateBranches/main.go index 0a524b094a7d..9e3677835503 100644 --- a/go/ql/test/query-tests/RedundantCode/DuplicateBranches/main.go +++ b/go/ql/test/query-tests/RedundantCode/DuplicateBranches/main.go @@ -3,7 +3,7 @@ package main import "fmt" func bad(x int) { - if x < 0 { // NOT OK + if x < 0 { // $ Alert // NOT OK fmt.Println("x is negative") } else { fmt.Println("x is negative") diff --git a/go/ql/test/query-tests/RedundantCode/DuplicateCondition/DuplicateCondition.go b/go/ql/test/query-tests/RedundantCode/DuplicateCondition/DuplicateCondition.go index a93bb546c425..2ad4ad8e0e49 100644 --- a/go/ql/test/query-tests/RedundantCode/DuplicateCondition/DuplicateCondition.go +++ b/go/ql/test/query-tests/RedundantCode/DuplicateCondition/DuplicateCondition.go @@ -1,9 +1,9 @@ package main func controller(msg string) { - if msg == "start" { + if msg == "start" { // $ Source start() - } else if msg == "start" { // NOT OK + } else if msg == "start" { // $ Alert // NOT OK stop() } else { panic("Message not understood.") diff --git a/go/ql/test/query-tests/RedundantCode/DuplicateCondition/DuplicateCondition.qlref b/go/ql/test/query-tests/RedundantCode/DuplicateCondition/DuplicateCondition.qlref index a6069ea94ad1..36bb8140f1a2 100644 --- a/go/ql/test/query-tests/RedundantCode/DuplicateCondition/DuplicateCondition.qlref +++ b/go/ql/test/query-tests/RedundantCode/DuplicateCondition/DuplicateCondition.qlref @@ -1 +1,2 @@ -RedundantCode/DuplicateCondition.ql +query: RedundantCode/DuplicateCondition.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/RedundantCode/DuplicateCondition/tst.go b/go/ql/test/query-tests/RedundantCode/DuplicateCondition/tst.go index 912f13fef7e6..60e88d978f6f 100644 --- a/go/ql/test/query-tests/RedundantCode/DuplicateCondition/tst.go +++ b/go/ql/test/query-tests/RedundantCode/DuplicateCondition/tst.go @@ -5,8 +5,8 @@ func check(x int) bool { } func main() { - if ok := check(42); ok { - } else if ok { // NOT OK + if ok := check(42); ok { // $ Source + } else if ok { // $ Alert // NOT OK } else if ok := check(23); ok { // OK } } diff --git a/go/ql/test/query-tests/RedundantCode/DuplicateSwitchCase/DuplicateSwitchCase.go b/go/ql/test/query-tests/RedundantCode/DuplicateSwitchCase/DuplicateSwitchCase.go index 1c902c1328be..d2b1d320f331 100644 --- a/go/ql/test/query-tests/RedundantCode/DuplicateSwitchCase/DuplicateSwitchCase.go +++ b/go/ql/test/query-tests/RedundantCode/DuplicateSwitchCase/DuplicateSwitchCase.go @@ -4,7 +4,7 @@ func controller(msg string) { switch { case msg == "start": start() - case msg == "start": + case msg == "start": // $ Alert stop() default: panic("Message not understood.") diff --git a/go/ql/test/query-tests/RedundantCode/DuplicateSwitchCase/DuplicateSwitchCase.qlref b/go/ql/test/query-tests/RedundantCode/DuplicateSwitchCase/DuplicateSwitchCase.qlref index 570b78b50543..005bb508043a 100644 --- a/go/ql/test/query-tests/RedundantCode/DuplicateSwitchCase/DuplicateSwitchCase.qlref +++ b/go/ql/test/query-tests/RedundantCode/DuplicateSwitchCase/DuplicateSwitchCase.qlref @@ -1 +1,2 @@ -RedundantCode/DuplicateSwitchCase.ql +query: RedundantCode/DuplicateSwitchCase.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/RedundantCode/DuplicateSwitchCase/tst.go b/go/ql/test/query-tests/RedundantCode/DuplicateSwitchCase/tst.go index c927cd3d6862..235be408143a 100644 --- a/go/ql/test/query-tests/RedundantCode/DuplicateSwitchCase/tst.go +++ b/go/ql/test/query-tests/RedundantCode/DuplicateSwitchCase/tst.go @@ -6,7 +6,7 @@ func check(x int) { case x < 42: - case x < 23: // NOT OK + case x < 23: // $ Alert // NOT OK } } diff --git a/go/ql/test/query-tests/RedundantCode/ExprHasNoEffect/ExprHasNoEffect.go b/go/ql/test/query-tests/RedundantCode/ExprHasNoEffect/ExprHasNoEffect.go index 3c8b85f1e674..3b647bc2a8a2 100644 --- a/go/ql/test/query-tests/RedundantCode/ExprHasNoEffect/ExprHasNoEffect.go +++ b/go/ql/test/query-tests/RedundantCode/ExprHasNoEffect/ExprHasNoEffect.go @@ -10,6 +10,6 @@ func (t Timestamp) addDays(d int) Timestamp { func test(t Timestamp) { fmt.Printf("Before: %s\n", t) - t.addDays(7) + t.addDays(7) // $ Alert fmt.Printf("After: %s\n", t) } diff --git a/go/ql/test/query-tests/RedundantCode/ExprHasNoEffect/ExprHasNoEffect.qlref b/go/ql/test/query-tests/RedundantCode/ExprHasNoEffect/ExprHasNoEffect.qlref index d13ada431941..bb4426132466 100644 --- a/go/ql/test/query-tests/RedundantCode/ExprHasNoEffect/ExprHasNoEffect.qlref +++ b/go/ql/test/query-tests/RedundantCode/ExprHasNoEffect/ExprHasNoEffect.qlref @@ -1 +1,2 @@ -RedundantCode/ExprHasNoEffect.ql +query: RedundantCode/ExprHasNoEffect.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/RedundantCode/ExprHasNoEffect/main.go b/go/ql/test/query-tests/RedundantCode/ExprHasNoEffect/main.go index e9c18030df55..960260b1fce5 100644 --- a/go/ql/test/query-tests/RedundantCode/ExprHasNoEffect/main.go +++ b/go/ql/test/query-tests/RedundantCode/ExprHasNoEffect/main.go @@ -23,10 +23,10 @@ func div(x int, y int) int { } func main() { - f1(42) // NOT OK + f1(42) // $ Alert // NOT OK f2(42) // OK - f1(f2(42)) // NOT OK - abs(-2) // NOT OK + f1(f2(42)) // $ Alert // NOT OK + abs(-2) // $ Alert // NOT OK div(1, 0) // OK dostuff() // OK cleanup() // OK diff --git a/go/ql/test/query-tests/RedundantCode/ImpossibleInterfaceNilCheck/ImpossibleInterfaceNilCheck.go b/go/ql/test/query-tests/RedundantCode/ImpossibleInterfaceNilCheck/ImpossibleInterfaceNilCheck.go index 00b015d3814d..f0013365e1fa 100644 --- a/go/ql/test/query-tests/RedundantCode/ImpossibleInterfaceNilCheck/ImpossibleInterfaceNilCheck.go +++ b/go/ql/test/query-tests/RedundantCode/ImpossibleInterfaceNilCheck/ImpossibleInterfaceNilCheck.go @@ -6,7 +6,7 @@ func niceFetch(url string) { var s string var e error s, e = fetch(url) - if e != nil { + if e != nil { // $ Alert fmt.Printf("Unable to fetch URL: %v\n", e) } else { fmt.Printf("URL contents: %s\n", s) diff --git a/go/ql/test/query-tests/RedundantCode/ImpossibleInterfaceNilCheck/ImpossibleInterfaceNilCheck.qlref b/go/ql/test/query-tests/RedundantCode/ImpossibleInterfaceNilCheck/ImpossibleInterfaceNilCheck.qlref index d858724be57a..0049d67433aa 100644 --- a/go/ql/test/query-tests/RedundantCode/ImpossibleInterfaceNilCheck/ImpossibleInterfaceNilCheck.qlref +++ b/go/ql/test/query-tests/RedundantCode/ImpossibleInterfaceNilCheck/ImpossibleInterfaceNilCheck.qlref @@ -1 +1,2 @@ -RedundantCode/ImpossibleInterfaceNilCheck.ql +query: RedundantCode/ImpossibleInterfaceNilCheck.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/RedundantCode/ImpossibleInterfaceNilCheck/tst.go b/go/ql/test/query-tests/RedundantCode/ImpossibleInterfaceNilCheck/tst.go index 81584045c131..e7716a7584a4 100644 --- a/go/ql/test/query-tests/RedundantCode/ImpossibleInterfaceNilCheck/tst.go +++ b/go/ql/test/query-tests/RedundantCode/ImpossibleInterfaceNilCheck/tst.go @@ -7,7 +7,7 @@ func test1() { var y interface{} = x fmt.Println(x == nil) fmt.Println(x == y) - fmt.Println(y == nil) // NOT OK + fmt.Println(y == nil) // $ Alert // NOT OK } func test2() { diff --git a/go/ql/test/query-tests/RedundantCode/NegativeLengthCheck/NegativeLengthCheck.go b/go/ql/test/query-tests/RedundantCode/NegativeLengthCheck/NegativeLengthCheck.go index 6ebdb224ee13..9c7460b94325 100644 --- a/go/ql/test/query-tests/RedundantCode/NegativeLengthCheck/NegativeLengthCheck.go +++ b/go/ql/test/query-tests/RedundantCode/NegativeLengthCheck/NegativeLengthCheck.go @@ -1,7 +1,7 @@ package main func getFirst(xs []int) int { - if len(xs) < 0 { + if len(xs) < 0 { // $ Alert panic("No elements provided") } return xs[0] diff --git a/go/ql/test/query-tests/RedundantCode/NegativeLengthCheck/NegativeLengthCheck.qlref b/go/ql/test/query-tests/RedundantCode/NegativeLengthCheck/NegativeLengthCheck.qlref index d3e9be220bf3..de3ae7284148 100644 --- a/go/ql/test/query-tests/RedundantCode/NegativeLengthCheck/NegativeLengthCheck.qlref +++ b/go/ql/test/query-tests/RedundantCode/NegativeLengthCheck/NegativeLengthCheck.qlref @@ -1 +1,2 @@ -RedundantCode/NegativeLengthCheck.ql +query: RedundantCode/NegativeLengthCheck.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/RedundantCode/NegativeLengthCheck/main.go b/go/ql/test/query-tests/RedundantCode/NegativeLengthCheck/main.go index f43f4851c5f0..9b145e293e20 100644 --- a/go/ql/test/query-tests/RedundantCode/NegativeLengthCheck/main.go +++ b/go/ql/test/query-tests/RedundantCode/NegativeLengthCheck/main.go @@ -3,7 +3,7 @@ package main import "os" func main() { - if len(os.Args) < 0 { // NOT OK + if len(os.Args) < 0 { // $ Alert // NOT OK println("No arguments provided.") } @@ -11,21 +11,21 @@ func main() { println("No arguments provided.") } - if cap(os.Args) < 0 { // NOT OK + if cap(os.Args) < 0 { // $ Alert // NOT OK println("Out of space!") } - if len(os.Args) <= -1 { // NOT OK + if len(os.Args) <= -1 { // $ Alert // NOT OK println("No arguments provided.") } - if len(os.Args) == -1 { // NOT OK + if len(os.Args) == -1 { // $ Alert // NOT OK println("No arguments provided.") } } func checkNegative(x uint) bool { - return x < 0 // NOT OK + return x < 0 // $ Alert // NOT OK } func checkNonPositive(x uint) bool { diff --git a/go/ql/test/query-tests/RedundantCode/RedundantExpr/RedundantExpr.go b/go/ql/test/query-tests/RedundantCode/RedundantExpr/RedundantExpr.go index 033f3883b0a7..283d0552be86 100644 --- a/go/ql/test/query-tests/RedundantCode/RedundantExpr/RedundantExpr.go +++ b/go/ql/test/query-tests/RedundantCode/RedundantExpr/RedundantExpr.go @@ -1,5 +1,5 @@ package main func avg(x, y float64) float64 { - return (x + x) / 2 + return (x + x) / 2 // $ Alert } diff --git a/go/ql/test/query-tests/RedundantCode/RedundantExpr/RedundantExpr.qlref b/go/ql/test/query-tests/RedundantCode/RedundantExpr/RedundantExpr.qlref index 23a5db7b419f..f9c95d27835a 100644 --- a/go/ql/test/query-tests/RedundantCode/RedundantExpr/RedundantExpr.qlref +++ b/go/ql/test/query-tests/RedundantCode/RedundantExpr/RedundantExpr.qlref @@ -1 +1,2 @@ -RedundantCode/RedundantExpr.ql +query: RedundantCode/RedundantExpr.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/RedundantCode/RedundantExpr/tst.go b/go/ql/test/query-tests/RedundantCode/RedundantExpr/tst.go index e4106fb7bfaa..1a0d38eb2feb 100644 --- a/go/ql/test/query-tests/RedundantCode/RedundantExpr/tst.go +++ b/go/ql/test/query-tests/RedundantCode/RedundantExpr/tst.go @@ -1,12 +1,12 @@ package main func foo(x int) int { - return x - x /* NOT OK */ + (x & x) /* NOT OK */ + return x - x /* NOT OK */ + (x & x) /* NOT OK */ // $ Alert } func bar(b bool, x float32) float32 { if b { - return (x + x) / 2 // NOT OK + return (x + x) / 2 // $ Alert // NOT OK } else { return (x * x) / 2 // OK } diff --git a/go/ql/test/query-tests/RedundantCode/RedundantRecover/RedundantRecover.qlref b/go/ql/test/query-tests/RedundantCode/RedundantRecover/RedundantRecover.qlref index c8997068734d..3f91b000a4cb 100644 --- a/go/ql/test/query-tests/RedundantCode/RedundantRecover/RedundantRecover.qlref +++ b/go/ql/test/query-tests/RedundantCode/RedundantRecover/RedundantRecover.qlref @@ -1 +1,2 @@ -RedundantCode/RedundantRecover.ql +query: RedundantCode/RedundantRecover.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/RedundantCode/RedundantRecover/RedundantRecover1.go b/go/ql/test/query-tests/RedundantCode/RedundantRecover/RedundantRecover1.go index d058dd0dfdea..3a9cc3f9cc23 100644 --- a/go/ql/test/query-tests/RedundantCode/RedundantRecover/RedundantRecover1.go +++ b/go/ql/test/query-tests/RedundantCode/RedundantRecover/RedundantRecover1.go @@ -3,7 +3,7 @@ package main import "fmt" func callRecover1() { - if recover() != nil { + if recover() != nil { // $ Alert fmt.Printf("recovered") } } diff --git a/go/ql/test/query-tests/RedundantCode/RedundantRecover/RedundantRecover2.go b/go/ql/test/query-tests/RedundantCode/RedundantRecover/RedundantRecover2.go index 4365cb7c9fe5..2627373ad279 100644 --- a/go/ql/test/query-tests/RedundantCode/RedundantRecover/RedundantRecover2.go +++ b/go/ql/test/query-tests/RedundantCode/RedundantRecover/RedundantRecover2.go @@ -1,6 +1,6 @@ package main func fun2() { - defer recover() + defer recover() // $ Alert panic("2") } diff --git a/go/ql/test/query-tests/RedundantCode/RedundantRecover/tst.go b/go/ql/test/query-tests/RedundantCode/RedundantRecover/tst.go index 0533a0609318..c9bebbd4bfe4 100644 --- a/go/ql/test/query-tests/RedundantCode/RedundantRecover/tst.go +++ b/go/ql/test/query-tests/RedundantCode/RedundantRecover/tst.go @@ -5,7 +5,7 @@ import "fmt" func callRecover3() { // This will have no effect because panics do not propagate down the stack, // only back up the stack - if recover() != nil { + if recover() != nil { // $ Alert fmt.Printf("recovered") } } diff --git a/go/ql/test/query-tests/RedundantCode/SelfAssignment/SelfAssignment.go b/go/ql/test/query-tests/RedundantCode/SelfAssignment/SelfAssignment.go index ab2e585e1988..00b971db61a8 100644 --- a/go/ql/test/query-tests/RedundantCode/SelfAssignment/SelfAssignment.go +++ b/go/ql/test/query-tests/RedundantCode/SelfAssignment/SelfAssignment.go @@ -9,5 +9,5 @@ func (r *Rect) setWidth(width int) { } func (r *Rect) setHeight(height int) { - height = height + height = height // $ Alert } diff --git a/go/ql/test/query-tests/RedundantCode/SelfAssignment/SelfAssignment.qlref b/go/ql/test/query-tests/RedundantCode/SelfAssignment/SelfAssignment.qlref index 3eebdc5dc73f..fcdd17256036 100644 --- a/go/ql/test/query-tests/RedundantCode/SelfAssignment/SelfAssignment.qlref +++ b/go/ql/test/query-tests/RedundantCode/SelfAssignment/SelfAssignment.qlref @@ -1 +1,2 @@ -RedundantCode/SelfAssignment.ql +query: RedundantCode/SelfAssignment.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/RedundantCode/SelfAssignment/tst.go b/go/ql/test/query-tests/RedundantCode/SelfAssignment/tst.go index 31a556ce551a..fef980cdc152 100644 --- a/go/ql/test/query-tests/RedundantCode/SelfAssignment/tst.go +++ b/go/ql/test/query-tests/RedundantCode/SelfAssignment/tst.go @@ -2,5 +2,5 @@ package main func main() { x := 42 - x = x // NOT OK + x = x // $ Alert // NOT OK } diff --git a/go/ql/test/query-tests/RedundantCode/ShiftOutOfRange/ShiftOutOfRange.go b/go/ql/test/query-tests/RedundantCode/ShiftOutOfRange/ShiftOutOfRange.go index aaa05763ce2a..64d1383393df 100644 --- a/go/ql/test/query-tests/RedundantCode/ShiftOutOfRange/ShiftOutOfRange.go +++ b/go/ql/test/query-tests/RedundantCode/ShiftOutOfRange/ShiftOutOfRange.go @@ -1,7 +1,7 @@ package main func shift(base int32) int32 { - return base << 40 + return base << 40 // $ Alert } var x1 = shift(1) diff --git a/go/ql/test/query-tests/RedundantCode/ShiftOutOfRange/ShiftOutOfRange.qlref b/go/ql/test/query-tests/RedundantCode/ShiftOutOfRange/ShiftOutOfRange.qlref index 223322f97762..2920410dfebb 100644 --- a/go/ql/test/query-tests/RedundantCode/ShiftOutOfRange/ShiftOutOfRange.qlref +++ b/go/ql/test/query-tests/RedundantCode/ShiftOutOfRange/ShiftOutOfRange.qlref @@ -1 +1,2 @@ -RedundantCode/ShiftOutOfRange.ql +query: RedundantCode/ShiftOutOfRange.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/RedundantCode/ShiftOutOfRange/main.go b/go/ql/test/query-tests/RedundantCode/ShiftOutOfRange/main.go index 4afb91d1750d..22d68cc6bac7 100644 --- a/go/ql/test/query-tests/RedundantCode/ShiftOutOfRange/main.go +++ b/go/ql/test/query-tests/RedundantCode/ShiftOutOfRange/main.go @@ -1,15 +1,15 @@ package main func bad1(x uint8) uint8 { - return x << 8 // NOT OK + return x << 8 // $ Alert // NOT OK } func bad2(y int32) int32 { - return y >> 33 // NOT OK + return y >> 33 // $ Alert // NOT OK } func bad3(z int) int { - return z << 64 // NOT OK + return z << 64 // $ Alert // NOT OK } func good1(x uint8) uint8 { diff --git a/go/ql/test/query-tests/RedundantCode/UnreachableStatement/UnreachableStatement.go b/go/ql/test/query-tests/RedundantCode/UnreachableStatement/UnreachableStatement.go index 10250238158d..a11218b99e15 100644 --- a/go/ql/test/query-tests/RedundantCode/UnreachableStatement/UnreachableStatement.go +++ b/go/ql/test/query-tests/RedundantCode/UnreachableStatement/UnreachableStatement.go @@ -2,7 +2,7 @@ package main func mul(xs []int) int { res := 1 - for i := 0; i < len(xs); i++ { + for i := 0; i < len(xs); i++ { // $ Alert x := xs[i] res *= x if res == 0 { diff --git a/go/ql/test/query-tests/RedundantCode/UnreachableStatement/UnreachableStatement.qlref b/go/ql/test/query-tests/RedundantCode/UnreachableStatement/UnreachableStatement.qlref index 645ea6222276..a705d9b8cff5 100644 --- a/go/ql/test/query-tests/RedundantCode/UnreachableStatement/UnreachableStatement.qlref +++ b/go/ql/test/query-tests/RedundantCode/UnreachableStatement/UnreachableStatement.qlref @@ -1 +1,2 @@ -RedundantCode/UnreachableStatement.ql +query: RedundantCode/UnreachableStatement.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/RedundantCode/UnreachableStatement/main.go b/go/ql/test/query-tests/RedundantCode/UnreachableStatement/main.go index 7903ef1ef846..cc26b717f605 100644 --- a/go/ql/test/query-tests/RedundantCode/UnreachableStatement/main.go +++ b/go/ql/test/query-tests/RedundantCode/UnreachableStatement/main.go @@ -10,16 +10,16 @@ func reachable() {} func test1() { return - unreachable() // NOT OK + unreachable() // $ Alert // NOT OK } func test2() { select {} - unreachable() // NOT OK + unreachable() // $ Alert // NOT OK } func test3() { - for i := 0; i < 10; unreachable() { // NOT OK + for i := 0; i < 10; unreachable() { // $ Alert // NOT OK return } } @@ -27,7 +27,7 @@ func test3() { func test4() { for true { } - unreachable() // NOT OK + unreachable() // $ Alert // NOT OK } func test5(cond bool) { @@ -46,15 +46,15 @@ func test6(cond bool) { } reachable() } - unreachable() // NOT OK + unreachable() // $ Alert // NOT OK } func test7(cond bool) { for true { continue - unreachable() // NOT OK + unreachable() // $ Alert // NOT OK } - unreachable() // NOT OK + unreachable() // $ Alert // NOT OK } func test8() { @@ -138,25 +138,25 @@ func test16() *mystruct { select {} // Flagged, as `return nil` is possible and preferable when the // return site is unreachable. - return &mystruct{0, true} + return &mystruct{0, true} // $ Alert } func test17() int { select {} // Flagged, as a nontrivial unreachable return - return test10(1) + return test10(1) // $ Alert } func test18() bool { select {} // Flagged, as a nontrivial unreachable return - return test10(1) == 1 + return test10(1) == 1 // $ Alert } func test19() mystruct { select {} // Flagged, as a nontrivial unreachable return - return mystruct{test10(1), test10(2) == 2} + return mystruct{test10(1), test10(2) == 2} // $ Alert } func main() {} diff --git a/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/IncompleteHostnameRegexp.go b/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/IncompleteHostnameRegexp.go index 073c8555efc0..3f290ccf9832 100644 --- a/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/IncompleteHostnameRegexp.go +++ b/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/IncompleteHostnameRegexp.go @@ -8,8 +8,8 @@ import ( func checkRedirect(req *http.Request, via []*http.Request) error { // BAD: the host of `req.URL` may be controlled by an attacker - re := "^((www|beta).)?example.com/" - if matched, _ := regexp.MatchString(re, req.URL.Host); matched { + re := "^((www|beta).)?example.com/" // $ Alert + if matched, _ := regexp.MatchString(re, req.URL.Host); matched { // $ Sink return nil } return errors.New("Invalid redirect") diff --git a/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/IncompleteHostnameRegexp.qlref b/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/IncompleteHostnameRegexp.qlref index 88d20f52eeed..0a6dac4bded6 100644 --- a/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/IncompleteHostnameRegexp.qlref +++ b/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/IncompleteHostnameRegexp.qlref @@ -1,2 +1,4 @@ query: Security/CWE-020/IncompleteHostnameRegexp.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/main.go b/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/main.go index 7eda0d7255a2..d677cab50d4a 100644 --- a/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/main.go +++ b/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/main.go @@ -37,30 +37,30 @@ func proxy() { HandleConnect(goproxy.AlwaysReject) // OK (rejecting all requests) proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile("^test1.github.com$"))). DoFunc(reject) // OK (rejecting all requests) - proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile("^test2.github.com$"))). - DoFunc(sometimesReject) // NOT OK (sometimes accepts requests) + proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile("^test2.github.com$"))). // $ Alert + DoFunc(sometimesReject) // NOT OK (sometimes accepts requests) } func main() { - regexp.Match(`https://www.example.com`, []byte("")) // NOT OK + regexp.Match(`https://www.example.com`, []byte("")) // $ Alert // NOT OK regexp.Match(`https://www\.example\.com`, []byte("")) // OK } -const sourceConst = `https://www.example.com` +const sourceConst = `https://www.example.com` // $ Alert const firstHalfConst = `https://www.example.` func concatenateStrings() { firstHalf := `https://www.example.` regexp.Match(firstHalf+`com`, []byte("")) // MISSING: NOT OK - regexp.Match(firstHalfConst+`com`, []byte("")) // NOT OK + regexp.Match(firstHalfConst+`com`, []byte("")) // $ Alert // NOT OK - regexp.Match(`https://www.example.`+`com`, []byte("")) // NOT OK + regexp.Match(`https://www.example.`+`com`, []byte("")) // $ Alert // NOT OK } func avoidDuplicateResults() { localVar1 := sourceConst localVar2 := localVar1 localVar3 := localVar2 - regexp.Match(localVar3, []byte("")) // NOT OK + regexp.Match(localVar3, []byte("")) // $ Sink // NOT OK } diff --git a/go/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck/IncompleteUrlSchemeCheck.go b/go/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck/IncompleteUrlSchemeCheck.go index f38261a032d1..69221d5c2129 100644 --- a/go/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck/IncompleteUrlSchemeCheck.go +++ b/go/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck/IncompleteUrlSchemeCheck.go @@ -4,7 +4,7 @@ import "net/url" func sanitizeUrl(urlstr string) string { u, err := url.Parse(urlstr) - if err != nil || u.Scheme == "javascript" { + if err != nil || u.Scheme == "javascript" { // $ Alert return "about:blank" } return urlstr diff --git a/go/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck/IncompleteUrlSchemeCheck.qlref b/go/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck/IncompleteUrlSchemeCheck.qlref index b27571781b34..0c088087e994 100644 --- a/go/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck/IncompleteUrlSchemeCheck.qlref +++ b/go/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck/IncompleteUrlSchemeCheck.qlref @@ -1 +1,2 @@ -Security/CWE-020/IncompleteUrlSchemeCheck.ql +query: Security/CWE-020/IncompleteUrlSchemeCheck.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck/main.go b/go/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck/main.go index ebe18f142f80..8b96f7c0af8c 100644 --- a/go/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck/main.go +++ b/go/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck/main.go @@ -14,7 +14,7 @@ func test(urlstr string) { urlstr = strings.NewReplacer("\n", "", "\r", "", "\t", "", "\u0000", "").Replace(urlstr) urlstr = strings.ToLower(urlstr) - if strings.HasPrefix(urlstr, "javascript:") || strings.HasPrefix(urlstr, "data:") { // NOT OK + if strings.HasPrefix(urlstr, "javascript:") || strings.HasPrefix(urlstr, "data:") { // $ Alert // NOT OK return } } diff --git a/go/ql/test/query-tests/Security/CWE-020/MissingRegexpAnchor/MissingRegexpAnchor.go b/go/ql/test/query-tests/Security/CWE-020/MissingRegexpAnchor/MissingRegexpAnchor.go index 60cb9d5b6bbc..6e7a567cb8cd 100644 --- a/go/ql/test/query-tests/Security/CWE-020/MissingRegexpAnchor/MissingRegexpAnchor.go +++ b/go/ql/test/query-tests/Security/CWE-020/MissingRegexpAnchor/MissingRegexpAnchor.go @@ -8,7 +8,7 @@ import ( func checkRedirect2(req *http.Request, via []*http.Request) error { // BAD: the host of `req.URL` may be controlled by an attacker - re := "https?://www\\.example\\.com/" + re := "https?://www\\.example\\.com/" // $ Alert if matched, _ := regexp.MatchString(re, req.URL.String()); matched { return nil } diff --git a/go/ql/test/query-tests/Security/CWE-020/MissingRegexpAnchor/MissingRegexpAnchor.qlref b/go/ql/test/query-tests/Security/CWE-020/MissingRegexpAnchor/MissingRegexpAnchor.qlref index b03fcd14a59e..ba73933077fe 100644 --- a/go/ql/test/query-tests/Security/CWE-020/MissingRegexpAnchor/MissingRegexpAnchor.qlref +++ b/go/ql/test/query-tests/Security/CWE-020/MissingRegexpAnchor/MissingRegexpAnchor.qlref @@ -1 +1,2 @@ -Security/CWE-020/MissingRegexpAnchor.ql +query: Security/CWE-020/MissingRegexpAnchor.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-020/MissingRegexpAnchor/main.go b/go/ql/test/query-tests/Security/CWE-020/MissingRegexpAnchor/main.go index efd10b7a6e2b..8674e2f2f383 100644 --- a/go/ql/test/query-tests/Security/CWE-020/MissingRegexpAnchor/main.go +++ b/go/ql/test/query-tests/Security/CWE-020/MissingRegexpAnchor/main.go @@ -6,36 +6,36 @@ import ( func main() { regexp.Match(`^a|`, []byte("")) // OK - regexp.Match(`^a|b`, []byte("")) // NOT OK + regexp.Match(`^a|b`, []byte("")) // $ Alert // NOT OK regexp.Match(`a|^b`, []byte("")) // OK regexp.Match(`^a|^b`, []byte("")) // OK - regexp.Match(`^a|b|c`, []byte("")) // NOT OK + regexp.Match(`^a|b|c`, []byte("")) // $ Alert // NOT OK regexp.Match(`a|^b|c`, []byte("")) // OK regexp.Match(`a|b|^c`, []byte("")) // OK regexp.Match(`^a|^b|c`, []byte("")) // OK regexp.Match(`(^a)|b`, []byte("")) // OK - regexp.Match(`^a|(b)`, []byte("")) // NOT OK + regexp.Match(`^a|(b)`, []byte("")) // $ Alert // NOT OK regexp.Match(`^a|(^b)`, []byte("")) // OK - regexp.Match(`^(a)|(b)`, []byte("")) // NOT OK + regexp.Match(`^(a)|(b)`, []byte("")) // $ Alert // NOT OK - regexp.Match(`a|b$`, []byte("")) // NOT OK + regexp.Match(`a|b$`, []byte("")) // $ Alert // NOT OK regexp.Match(`a$|b`, []byte("")) // OK regexp.Match(`a$|b$`, []byte("")) // OK - regexp.Match(`a|b|c$`, []byte("")) // NOT OK + regexp.Match(`a|b|c$`, []byte("")) // $ Alert // NOT OK regexp.Match(`a|b$|c`, []byte("")) // OK regexp.Match(`a$|b|c`, []byte("")) // OK regexp.Match(`a|b$|c$`, []byte("")) // OK regexp.Match(`a|(b$)`, []byte("")) // OK - regexp.Match(`(a)|b$`, []byte("")) // NOT OK + regexp.Match(`(a)|b$`, []byte("")) // $ Alert // NOT OK regexp.Match(`(a$)|b$`, []byte("")) // OK - regexp.Match(`(a)|(b)$`, []byte("")) // NOT OK + regexp.Match(`(a)|(b)$`, []byte("")) // $ Alert // NOT OK - regexp.Match(`https?://good.com`, []byte("http://evil.com/?http://good.com")) // NOT OK + regexp.Match(`https?://good.com`, []byte("http://evil.com/?http://good.com")) // $ Alert // NOT OK regexp.Match(`^https?://good.com`, []byte("http://evil.com/?http://good.com")) // OK - regexp.Match(`www\.example\.com`, []byte("")) // NOT OK + regexp.Match(`www\.example\.com`, []byte("")) // $ Alert // NOT OK regexp.Match(`^www\.example\.com`, []byte("")) // OK regexp.Match(`\Awww\.example\.com`, []byte("")) // OK regexp.Match(`www\.example\.com$`, []byte("")) // OK diff --git a/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.go b/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.go index d9f2199fd522..4194d79c2621 100644 --- a/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.go +++ b/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.go @@ -3,7 +3,7 @@ package main import "regexp" func broken(hostNames []byte) string { - var hostRe = regexp.MustCompile("\bforbidden.host.org") + var hostRe = regexp.MustCompile("\bforbidden.host.org") // $ Alert if hostRe.Match(hostNames) { return "Must not target forbidden.host.org" } else { diff --git a/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.qlref b/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.qlref index 727f3528b23c..17c2ba019cb2 100644 --- a/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.qlref +++ b/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.qlref @@ -1 +1,2 @@ -Security/CWE-020/SuspiciousCharacterInRegexp.ql +query: Security/CWE-020/SuspiciousCharacterInRegexp.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/test.go b/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/test.go index ff3da9b8496d..a872de930737 100644 --- a/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/test.go +++ b/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/test.go @@ -4,23 +4,23 @@ import "regexp" func main() { // many backslashes - regexp.MustCompile("\a") // BAD + regexp.MustCompile("\a") // $ Alert // BAD regexp.MustCompile("\\a") - regexp.MustCompile("\\\a") // BAD - regexp.MustCompile("x\\\a") // BAD + regexp.MustCompile("\\\a") // $ Alert // BAD + regexp.MustCompile("x\\\a") // $ Alert // BAD regexp.MustCompile("\\\\a") - regexp.MustCompile("\\\\\a") // BAD + regexp.MustCompile("\\\\\a") // $ Alert // BAD regexp.MustCompile("\\\\\\a") - regexp.MustCompile("\\\\\\\a") // BAD + regexp.MustCompile("\\\\\\\a") // $ Alert // BAD regexp.MustCompile("\\\\\\\\a") - regexp.MustCompile("\\\\\\\\\a") // BAD + regexp.MustCompile("\\\\\\\\\a") // $ Alert // BAD regexp.MustCompile("\\\\\\\\\\a") // BAD: probably a mistake: - regexp.MustCompile("hello\aworld") - regexp.MustCompile("hello\\\aworld") - regexp.MustCompile("hello\bworld") - regexp.MustCompile("hello\\\bworld") + regexp.MustCompile("hello\aworld") // $ Alert + regexp.MustCompile("hello\\\aworld") // $ Alert + regexp.MustCompile("hello\bworld") // $ Alert + regexp.MustCompile("hello\\\bworld") // $ Alert // GOOD: more likely deliberate: regexp.MustCompile("hello\\aworld") regexp.MustCompile("hello\x07world") diff --git a/go/ql/test/query-tests/Security/CWE-022/GorillaMuxDefault/TaintedPath.qlref b/go/ql/test/query-tests/Security/CWE-022/GorillaMuxDefault/TaintedPath.qlref index 1e9166dd1cae..688f7b5136f7 100644 --- a/go/ql/test/query-tests/Security/CWE-022/GorillaMuxDefault/TaintedPath.qlref +++ b/go/ql/test/query-tests/Security/CWE-022/GorillaMuxDefault/TaintedPath.qlref @@ -1,2 +1,4 @@ query: Security/CWE-022/TaintedPath.ql -postprocess: utils/test//PrettyPrintModels.ql \ No newline at end of file +postprocess: + - utils/test//PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-022/GorillaMuxSkipClean/MuxClean.go b/go/ql/test/query-tests/Security/CWE-022/GorillaMuxSkipClean/MuxClean.go index cb3b5d2a7b89..2767b5e6b5a0 100644 --- a/go/ql/test/query-tests/Security/CWE-022/GorillaMuxSkipClean/MuxClean.go +++ b/go/ql/test/query-tests/Security/CWE-022/GorillaMuxSkipClean/MuxClean.go @@ -10,8 +10,8 @@ import ( // BAD: Gorilla's `Vars` is not a sanitizer as `Router.SkipClean` has been called func GorillaHandler(w http.ResponseWriter, r *http.Request) { - not_tainted_path := mux.Vars(r)["id"] - data, _ := ioutil.ReadFile(filepath.Join("/home/user/", not_tainted_path)) + not_tainted_path := mux.Vars(r)["id"] // $ Source + data, _ := ioutil.ReadFile(filepath.Join("/home/user/", not_tainted_path)) // $ Alert w.Write(data) } diff --git a/go/ql/test/query-tests/Security/CWE-022/GorillaMuxSkipClean/TaintedPath.qlref b/go/ql/test/query-tests/Security/CWE-022/GorillaMuxSkipClean/TaintedPath.qlref index 1e9166dd1cae..688f7b5136f7 100644 --- a/go/ql/test/query-tests/Security/CWE-022/GorillaMuxSkipClean/TaintedPath.qlref +++ b/go/ql/test/query-tests/Security/CWE-022/GorillaMuxSkipClean/TaintedPath.qlref @@ -1,2 +1,4 @@ query: Security/CWE-022/TaintedPath.ql -postprocess: utils/test//PrettyPrintModels.ql \ No newline at end of file +postprocess: + - utils/test//PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-022/TaintedPath.go b/go/ql/test/query-tests/Security/CWE-022/TaintedPath.go index 65da5caecd2c..812b56f7c94b 100644 --- a/go/ql/test/query-tests/Security/CWE-022/TaintedPath.go +++ b/go/ql/test/query-tests/Security/CWE-022/TaintedPath.go @@ -12,14 +12,14 @@ import ( ) func handler(w http.ResponseWriter, r *http.Request) { - tainted_path := r.URL.Query()["path"][0] + tainted_path := r.URL.Query()["path"][0] // $ Source[go/path-injection] // BAD: This could read any file on the file system - data, _ := ioutil.ReadFile(tainted_path) + data, _ := ioutil.ReadFile(tainted_path) // $ Alert[go/path-injection] w.Write(data) // BAD: This could still read any file on the file system - data, _ = ioutil.ReadFile(filepath.Join("/home/user/", tainted_path)) + data, _ = ioutil.ReadFile(filepath.Join("/home/user/", tainted_path)) // $ Alert[go/path-injection] w.Write(data) // GOOD: This can only read inside the provided safe path @@ -71,7 +71,7 @@ func handler(w http.ResponseWriter, r *http.Request) { // BAD: Sanitized by path.Clean with a prepended '/' forcing interpretation // as an absolute path, however is not sufficient for Windows paths. - data, _ = ioutil.ReadFile(path.Clean("/" + tainted_path)) + data, _ = ioutil.ReadFile(path.Clean("/" + tainted_path)) // $ Alert[go/path-injection] w.Write(data) // GOOD: Multipart.Form.FileHeader.Filename sanitized by filepath.Base when calling ParseMultipartForm diff --git a/go/ql/test/query-tests/Security/CWE-022/TaintedPath.qlref b/go/ql/test/query-tests/Security/CWE-022/TaintedPath.qlref index 78ce25b1921f..6eb2e94892f2 100644 --- a/go/ql/test/query-tests/Security/CWE-022/TaintedPath.qlref +++ b/go/ql/test/query-tests/Security/CWE-022/TaintedPath.qlref @@ -1,2 +1,4 @@ query: Security/CWE-022/TaintedPath.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlink.go b/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlink.go index 8a3016f9c31c..66a8763a2b05 100644 --- a/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlink.go +++ b/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlink.go @@ -28,7 +28,7 @@ func unzipSymlinkBad(f io.Reader, target string) { break } if isRel(header.Linkname, target) && isRel(header.Name, target) { - os.Symlink(header.Linkname, header.Name) + os.Symlink(header.Linkname, header.Name) // $ Alert[go/unsafe-unzip-symlink] } } } @@ -40,7 +40,7 @@ func unzipSymlinkBadZip(f io.ReaderAt, target string) { linkNameBytes, _ := ioutil.ReadAll(linkData) linkName := string(linkNameBytes) if isRel(linkName, target) && isRel(header.Name, target) { - os.Symlink(linkName, header.Name) + os.Symlink(linkName, header.Name) // $ Alert[go/unsafe-unzip-symlink] } } } @@ -109,7 +109,7 @@ func getNextHeader(f *tar.Reader) (*tar.Header, error) { } func writeSymlink(linkName, fileName string) { - os.Symlink(linkName, fileName) + os.Symlink(linkName, fileName) // $ Sink[go/unsafe-unzip-symlink] } // BAD: a variant of `unzipSymlinkBad` where the tar-read and symlink @@ -123,7 +123,7 @@ func unzipSymlinkBadFactored(f io.Reader, target string) { break } if isRel(header.Linkname, target) && isRel(header.Name, target) { - writeSymlink(header.Linkname, header.Name) + writeSymlink(header.Linkname, header.Name) // $ Alert[go/unsafe-unzip-symlink] } } } diff --git a/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlink.qlref b/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlink.qlref index a40aa6194e10..5971b0737351 100644 --- a/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlink.qlref +++ b/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlink.qlref @@ -1,2 +1,4 @@ query: Security/CWE-022/UnsafeUnzipSymlink.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlinkGood.go b/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlinkGood.go index dde03db263d0..d662246a9c26 100644 --- a/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlinkGood.go +++ b/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlinkGood.go @@ -58,7 +58,7 @@ func isRelGoodReadlink(candidate, target string) bool { if filepath.IsAbs(candidate) { return false } - realpath, err := os.Readlink(filepath.Join(target, candidate)) + realpath, err := os.Readlink(filepath.Join(target, candidate)) // $ Sink[go/zipslip] if err != nil { return false } @@ -69,7 +69,7 @@ func isRelGoodReadlink(candidate, target string) bool { func unzipSymlinkGoodReadlink(f io.Reader, target string) { r := tar.NewReader(f) for { - header, err := r.Next() + header, err := r.Next() // $ Alert[go/zipslip] if err != nil { break } diff --git a/go/ql/test/query-tests/Security/CWE-022/ZipSlip.go b/go/ql/test/query-tests/Security/CWE-022/ZipSlip.go index 1628eabbef98..936c3c8e9a26 100644 --- a/go/ql/test/query-tests/Security/CWE-022/ZipSlip.go +++ b/go/ql/test/query-tests/Security/CWE-022/ZipSlip.go @@ -11,6 +11,6 @@ func unzip(f string) { for _, f := range r.File { p, _ := filepath.Abs(f.Name) // BAD: This could overwrite any file on the file system - ioutil.WriteFile(p, []byte("present"), 0666) - } + ioutil.WriteFile(p, []byte("present"), 0666) // $ Sink[go/zipslip] + } // $ Alert[go/zipslip] } diff --git a/go/ql/test/query-tests/Security/CWE-022/ZipSlip.qlref b/go/ql/test/query-tests/Security/CWE-022/ZipSlip.qlref index da30bbaf10df..39acfb7ca4a8 100644 --- a/go/ql/test/query-tests/Security/CWE-022/ZipSlip.qlref +++ b/go/ql/test/query-tests/Security/CWE-022/ZipSlip.qlref @@ -1,2 +1,4 @@ query: Security/CWE-022/ZipSlip.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-022/tarslip.go b/go/ql/test/query-tests/Security/CWE-022/tarslip.go index 37b3a32715c3..f7e01ff05653 100644 --- a/go/ql/test/query-tests/Security/CWE-022/tarslip.go +++ b/go/ql/test/query-tests/Security/CWE-022/tarslip.go @@ -12,8 +12,8 @@ import ( func untarBad(reader io.Reader, prefix string) { tarReader := tar.NewReader(reader) - header, _ := tarReader.Next() - os.MkdirAll(path.Dir(header.Name), 0755) // NOT OK + header, _ := tarReader.Next() // $ Alert[go/zipslip] + os.MkdirAll(path.Dir(header.Name), 0755) // $ Sink[go/zipslip] // NOT OK } func untarGood(reader io.Reader, prefix string) { diff --git a/go/ql/test/query-tests/Security/CWE-022/tst.go b/go/ql/test/query-tests/Security/CWE-022/tst.go index 599faccf0f1b..4cf3a77c4c8d 100644 --- a/go/ql/test/query-tests/Security/CWE-022/tst.go +++ b/go/ql/test/query-tests/Security/CWE-022/tst.go @@ -26,7 +26,7 @@ func unzip2(f string, root string) { if err == nil { ioutil.WriteFile(filepath.Join(root, relpath), []byte("present"), 0666) // OK } - ioutil.WriteFile(path, []byte("present"), 0666) // NOT OK + ioutil.WriteFile(path, []byte("present"), 0666) // $ Sink[go/zipslip] // NOT OK if containedIn(path, root) { ioutil.WriteFile(path, []byte("present"), 0666) // OK } @@ -40,7 +40,7 @@ func unzip2(f string, root string) { if containedIn(f.Name, root) { ioutil.WriteFile(f.Name, []byte("present"), 0666) // OK } - } + } // $ Alert[go/zipslip] } func containedIn(f string, root string) bool { diff --git a/go/ql/test/query-tests/Security/CWE-078/ArgumentInjection.go b/go/ql/test/query-tests/Security/CWE-078/ArgumentInjection.go index d38d4662542e..7519916afe0a 100644 --- a/go/ql/test/query-tests/Security/CWE-078/ArgumentInjection.go +++ b/go/ql/test/query-tests/Security/CWE-078/ArgumentInjection.go @@ -6,7 +6,7 @@ import ( ) func handler2(req *http.Request) { - path := req.URL.Query()["path"][0] - cmd := exec.Command("rsync", path, "/tmp") + path := req.URL.Query()["path"][0] // $ Source[go/command-injection] + cmd := exec.Command("rsync", path, "/tmp") // $ Alert[go/command-injection] cmd.Run() } diff --git a/go/ql/test/query-tests/Security/CWE-078/CommandInjection.go b/go/ql/test/query-tests/Security/CWE-078/CommandInjection.go index ff046f240844..a8af53b7fc5d 100644 --- a/go/ql/test/query-tests/Security/CWE-078/CommandInjection.go +++ b/go/ql/test/query-tests/Security/CWE-078/CommandInjection.go @@ -6,7 +6,7 @@ import ( ) func handler(req *http.Request) { - cmdName := req.URL.Query()["cmd"][0] - cmd := exec.Command(cmdName) + cmdName := req.URL.Query()["cmd"][0] // $ Source[go/command-injection] + cmd := exec.Command(cmdName) // $ Alert[go/command-injection] cmd.Run() } diff --git a/go/ql/test/query-tests/Security/CWE-078/CommandInjection.qlref b/go/ql/test/query-tests/Security/CWE-078/CommandInjection.qlref index 2b07372975ff..b1836a682e3b 100644 --- a/go/ql/test/query-tests/Security/CWE-078/CommandInjection.qlref +++ b/go/ql/test/query-tests/Security/CWE-078/CommandInjection.qlref @@ -1,2 +1,4 @@ query: Security/CWE-078/CommandInjection.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-078/CommandInjection2.go b/go/ql/test/query-tests/Security/CWE-078/CommandInjection2.go index 943a3f72f05a..975ff72d1772 100644 --- a/go/ql/test/query-tests/Security/CWE-078/CommandInjection2.go +++ b/go/ql/test/query-tests/Security/CWE-078/CommandInjection2.go @@ -10,9 +10,9 @@ import ( ) func handlerExample(req *http.Request) { - imageName := req.URL.Query()["imageName"][0] + imageName := req.URL.Query()["imageName"][0] // $ Source[go/command-injection] outputPath := "/tmp/output.svg" - cmd := exec.Command("sh", "-c", fmt.Sprintf("imagetool %s > %s", imageName, outputPath)) // NOT OK - correctly flagged + cmd := exec.Command("sh", "-c", fmt.Sprintf("imagetool %s > %s", imageName, outputPath)) // $ Alert[go/command-injection] // NOT OK - correctly flagged cmd.Run() // ... } @@ -38,10 +38,10 @@ func handlerExample2(req *http.Request) { } func handlerExample3(req *http.Request) { - imageName := req.URL.Query()["imageName"][0] + imageName := req.URL.Query()["imageName"][0] // $ Source[go/command-injection] outputPath := "/tmp/output.svg" - cmd := exec.Command("sh", "-c", fmt.Sprintf("imagetool %s > %s", imageName, outputPath)) // NOT OK - correctly flagged + cmd := exec.Command("sh", "-c", fmt.Sprintf("imagetool %s > %s", imageName, outputPath)) // $ Alert[go/command-injection] // NOT OK - correctly flagged cmd.Run() // Validate the imageName with a regular expression diff --git a/go/ql/test/query-tests/Security/CWE-078/GitSubcommands.go b/go/ql/test/query-tests/Security/CWE-078/GitSubcommands.go index 5e72e5825afd..80322dcd27bf 100644 --- a/go/ql/test/query-tests/Security/CWE-078/GitSubcommands.go +++ b/go/ql/test/query-tests/Security/CWE-078/GitSubcommands.go @@ -8,13 +8,13 @@ import ( // BAD: using git subcommands that are vulnerable to arbitrary remote command execution func gitSubcommandsBad(req *http.Request) { - tainted := req.URL.Query()["cmd"][0] + tainted := req.URL.Query()["cmd"][0] // $ Source[go/command-injection] - exec.Command("git", "clone", tainted) - exec.Command("git", "fetch", tainted) - exec.Command("git", "pull", tainted) - exec.Command("git", "ls-remote", tainted) - exec.Command("git", "fetch-pack", tainted) + exec.Command("git", "clone", tainted) // $ Alert[go/command-injection] + exec.Command("git", "fetch", tainted) // $ Alert[go/command-injection] + exec.Command("git", "pull", tainted) // $ Alert[go/command-injection] + exec.Command("git", "ls-remote", tainted) // $ Alert[go/command-injection] + exec.Command("git", "fetch-pack", tainted) // $ Alert[go/command-injection] } // GOOD: using a sampling of git subcommands that are not vulnerable to arbitrary remote command execution @@ -30,11 +30,11 @@ func gitSubcommandsGood(req *http.Request) { // BAD: using git subcommands that are vulnerable to arbitrary remote command execution func gitSubcommandsGood2(req *http.Request) { - tainted := req.URL.Query()["cmd"][0] + tainted := req.URL.Query()["cmd"][0] // $ Source[go/command-injection] if !strings.HasPrefix(tainted, "--") { exec.Command("git", "clone", tainted) // GOOD, `tainted` cannot start with "--" } else { - exec.Command("git", "clone", tainted) // BAD, `tainted` can start with "--" + exec.Command("git", "clone", tainted) // $ Alert[go/command-injection] // BAD, `tainted` can start with "--" } } diff --git a/go/ql/test/query-tests/Security/CWE-078/SanitizingDoubleDash.go b/go/ql/test/query-tests/Security/CWE-078/SanitizingDoubleDash.go index 0428df550868..9a8692319bb2 100644 --- a/go/ql/test/query-tests/Security/CWE-078/SanitizingDoubleDash.go +++ b/go/ql/test/query-tests/Security/CWE-078/SanitizingDoubleDash.go @@ -6,12 +6,12 @@ import ( ) func testDoubleDashSanitizes(req *http.Request) { - tainted := req.URL.Query()["cmd"][0] + tainted := req.URL.Query()["cmd"][0] // $ Source[go/command-injection] // BAD: no sanitizing "--" preceding tainted data { arrayLit := [1]string{tainted} - exec.Command("git", arrayLit[:]...) + exec.Command("git", arrayLit[:]...) // $ Alert[go/command-injection] } // GOOD: sanitizing "--" preceding tainted data @@ -37,7 +37,7 @@ func testDoubleDashSanitizes(req *http.Request) { { arrayLit := []string{} arrayLit = append(arrayLit, tainted, "--") - exec.Command("git", arrayLit...) + exec.Command("git", arrayLit...) // $ Alert[go/command-injection] } // GOOD: sanitizing "--" preceding tainted data, built in two steps @@ -51,7 +51,7 @@ func testDoubleDashSanitizes(req *http.Request) { { arrayLit := []string{tainted} arrayLit = append(arrayLit, "--") - exec.Command("git", arrayLit...) + exec.Command("git", arrayLit...) // $ Alert[go/command-injection] } // GOOD: sanitizing "--" preceding tainted data, built in three steps @@ -67,7 +67,7 @@ func testDoubleDashSanitizes(req *http.Request) { arrayLit := []string{"something else"} arrayLit = append(arrayLit, tainted) arrayLit = append(arrayLit, "--") - exec.Command("git", arrayLit...) + exec.Command("git", arrayLit...) // $ Alert[go/command-injection] } // GOOD: sanitizing "--" preceding tainted data, used directly in a Command @@ -77,7 +77,7 @@ func testDoubleDashSanitizes(req *http.Request) { // BAD: sanitizing "--" comes after tainted data, used directly in a Command { - exec.Command("git", tainted, "--") + exec.Command("git", tainted, "--") // $ Alert[go/command-injection] } // GOOD: sanitizing "--" preceding tainted data, used directly in a Command, after several other arguments @@ -89,66 +89,66 @@ func testDoubleDashSanitizes(req *http.Request) { // This test mirrors testDoubleDashSanitizes above, but uses sudo instead of git, where "--" is not sanitizing. // All cases are therefore BAD. func testDoubleDashIrrelevant(req *http.Request) { - tainted := req.URL.Query()["cmd"][0] + tainted := req.URL.Query()["cmd"][0] // $ Source[go/command-injection] { arrayLit := [1]string{tainted} - exec.Command("sudo", arrayLit[:]...) // BAD + exec.Command("sudo", arrayLit[:]...) // $ Alert[go/command-injection] // BAD } { arrayLit := [2]string{"--", tainted} - exec.Command("sudo", arrayLit[:]...) // BAD + exec.Command("sudo", arrayLit[:]...) // $ Alert[go/command-injection] // BAD } { arrayLit := []string{"--", tainted} - exec.Command("sudo", arrayLit...) // BAD + exec.Command("sudo", arrayLit...) // $ Alert[go/command-injection] // BAD } { arrayLit := []string{} arrayLit = append(arrayLit, "--", tainted) - exec.Command("sudo", arrayLit...) // BAD + exec.Command("sudo", arrayLit...) // $ Alert[go/command-injection] // BAD } { arrayLit := []string{} arrayLit = append(arrayLit, tainted, "--") - exec.Command("sudo", arrayLit...) // BAD + exec.Command("sudo", arrayLit...) // $ Alert[go/command-injection] // BAD } { arrayLit := []string{"--"} arrayLit = append(arrayLit, tainted) - exec.Command("sudo", arrayLit...) // BAD + exec.Command("sudo", arrayLit...) // $ Alert[go/command-injection] // BAD } { arrayLit := []string{tainted} arrayLit = append(arrayLit, "--") - exec.Command("sudo", arrayLit...) // BAD + exec.Command("sudo", arrayLit...) // $ Alert[go/command-injection] // BAD } { arrayLit := []string{"--"} arrayLit = append(arrayLit, "something else") arrayLit = append(arrayLit, tainted) - exec.Command("sudo", arrayLit...) // BAD + exec.Command("sudo", arrayLit...) // $ Alert[go/command-injection] // BAD } { arrayLit := []string{"something else"} arrayLit = append(arrayLit, tainted) arrayLit = append(arrayLit, "--") - exec.Command("sudo", arrayLit...) // BAD + exec.Command("sudo", arrayLit...) // $ Alert[go/command-injection] // BAD } { - exec.Command("sudo", "--", tainted) // BAD + exec.Command("sudo", "--", tainted) // $ Alert[go/command-injection] // BAD } { - exec.Command("sudo", tainted, "--") // BAD + exec.Command("sudo", tainted, "--") // $ Alert[go/command-injection] // BAD } } diff --git a/go/ql/test/query-tests/Security/CWE-078/StoredCommand.go b/go/ql/test/query-tests/Security/CWE-078/StoredCommand.go index 5b7c16d0c590..ee38e54f4dab 100644 --- a/go/ql/test/query-tests/Security/CWE-078/StoredCommand.go +++ b/go/ql/test/query-tests/Security/CWE-078/StoredCommand.go @@ -8,9 +8,9 @@ import ( var db *sql.DB func run(query string) { - rows, _ := db.Query(query) + rows, _ := db.Query(query) // $ Source[go/stored-command] var cmdName string rows.Scan(&cmdName) - cmd := exec.Command(cmdName) + cmd := exec.Command(cmdName) // $ Alert[go/stored-command] cmd.Run() } diff --git a/go/ql/test/query-tests/Security/CWE-078/StoredCommand.qlref b/go/ql/test/query-tests/Security/CWE-078/StoredCommand.qlref index 92c41892880b..d1bc2b0f697b 100644 --- a/go/ql/test/query-tests/Security/CWE-078/StoredCommand.qlref +++ b/go/ql/test/query-tests/Security/CWE-078/StoredCommand.qlref @@ -1,2 +1,4 @@ query: Security/CWE-078/StoredCommand.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-089/SqlInjection.go b/go/ql/test/query-tests/Security/CWE-089/SqlInjection.go index 0df976d93c3f..9e36ea24c99e 100644 --- a/go/ql/test/query-tests/Security/CWE-089/SqlInjection.go +++ b/go/ql/test/query-tests/Security/CWE-089/SqlInjection.go @@ -8,6 +8,6 @@ import ( func handler(db *sql.DB, req *http.Request) { q := fmt.Sprintf("SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='%s' ORDER BY PRICE", - req.URL.Query()["category"]) - db.Query(q) + req.URL.Query()["category"]) // $ Source[go/sql-injection] + db.Query(q) // $ Alert[go/sql-injection] } diff --git a/go/ql/test/query-tests/Security/CWE-089/SqlInjection.qlref b/go/ql/test/query-tests/Security/CWE-089/SqlInjection.qlref index b6916bd2cd46..e19181577447 100644 --- a/go/ql/test/query-tests/Security/CWE-089/SqlInjection.qlref +++ b/go/ql/test/query-tests/Security/CWE-089/SqlInjection.qlref @@ -1,2 +1,4 @@ query: Security/CWE-089/SqlInjection.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-089/StringBreak.go b/go/ql/test/query-tests/Security/CWE-089/StringBreak.go index 5667ca350356..26cb9986c91d 100644 --- a/go/ql/test/query-tests/Security/CWE-089/StringBreak.go +++ b/go/ql/test/query-tests/Security/CWE-089/StringBreak.go @@ -8,10 +8,10 @@ import ( ) func save(id string, version interface{}) { - versionJSON, _ := json.Marshal(version) + versionJSON, _ := json.Marshal(version) // $ Source[go/unsafe-quoting] sq.StatementBuilder. Insert("resources"). Columns("resource_id", "version_md5"). - Values(id, sq.Expr(fmt.Sprintf("md5('%s')", versionJSON))). + Values(id, sq.Expr(fmt.Sprintf("md5('%s')", versionJSON))). // $ Alert[go/unsafe-quoting] Exec() } diff --git a/go/ql/test/query-tests/Security/CWE-089/StringBreak.qlref b/go/ql/test/query-tests/Security/CWE-089/StringBreak.qlref index 45a8c4191347..096091bde4c4 100644 --- a/go/ql/test/query-tests/Security/CWE-089/StringBreak.qlref +++ b/go/ql/test/query-tests/Security/CWE-089/StringBreak.qlref @@ -1,2 +1,4 @@ query: Security/CWE-089/StringBreak.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-089/StringBreakMismatched.go b/go/ql/test/query-tests/Security/CWE-089/StringBreakMismatched.go index c838d5f6b7da..70f3af40d6f5 100644 --- a/go/ql/test/query-tests/Security/CWE-089/StringBreakMismatched.go +++ b/go/ql/test/query-tests/Security/CWE-089/StringBreakMismatched.go @@ -10,23 +10,23 @@ import ( // Bad because quote characters are removed before concatenation, // but then enclosed in a different enclosing quote: func mismatch1(id string, version interface{}) { - versionJSON, _ := json.Marshal(version) + versionJSON, _ := json.Marshal(version) // $ Source[go/unsafe-quoting] escaped := strings.Replace(string(versionJSON), "\"", "", -1) sq.StatementBuilder. Insert("resources"). Columns("resource_id", "version_md5"). - Values(id, sq.Expr("'"+escaped+"'")). + Values(id, sq.Expr("'"+escaped+"'")). // $ Alert[go/unsafe-quoting] Exec() } // Bad because quote characters are removed before concatenation, // but then enclosed in a different enclosing quote: func mismatch2(id string, version interface{}) { - versionJSON, _ := json.Marshal(version) + versionJSON, _ := json.Marshal(version) // $ Source[go/unsafe-quoting] escaped := strings.Replace(string(versionJSON), "'", "", -1) sq.StatementBuilder. Insert("resources"). Columns("resource_id", "version_md5"). - Values(id, sq.Expr("\""+escaped+"\"")). + Values(id, sq.Expr("\""+escaped+"\"")). // $ Alert[go/unsafe-quoting] Exec() } diff --git a/go/ql/test/query-tests/Security/CWE-089/issue48.go b/go/ql/test/query-tests/Security/CWE-089/issue48.go index 2c23b617190b..9ef91eb13509 100644 --- a/go/ql/test/query-tests/Security/CWE-089/issue48.go +++ b/go/ql/test/query-tests/Security/CWE-089/issue48.go @@ -14,29 +14,29 @@ func handler1(db *sql.DB, req *http.Request) { // read data from request body and unmarshal to a indeterminacy struct // POST: {"a": "b", "category": "test"} var RequestDataFromJson map[string]interface{} - b, _ := ioutil.ReadAll(req.Body) + b, _ := ioutil.ReadAll(req.Body) // $ Source[go/sql-injection] json.Unmarshal(b, &RequestDataFromJson) q3 := fmt.Sprintf("SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='%s' ORDER BY PRICE", RequestDataFromJson["category"]) - db.Query(q3) // NOT OK + db.Query(q3) // $ Alert[go/sql-injection] // NOT OK // read data from request body and unmarshal to a determined struct // POST: {"id": "1", "category": "test"} var RequestDataFromJson2 RequestStruct - b2, _ := ioutil.ReadAll(req.Body) + b2, _ := ioutil.ReadAll(req.Body) // $ Source[go/sql-injection] json.Unmarshal(b2, &RequestDataFromJson2) q4 := fmt.Sprintf("SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='%s' ORDER BY PRICE", RequestDataFromJson2.Category) - db.Query(q4) // NOT OK + db.Query(q4) // $ Alert[go/sql-injection] // NOT OK // read json data from a url parameter // GET: ?json={"id": 1, "category": "test"} var RequestDataFromJson3 RequestStruct - json.Unmarshal([]byte(req.URL.Query()["json"][0]), &RequestDataFromJson3) + json.Unmarshal([]byte(req.URL.Query()["json"][0]), &RequestDataFromJson3) // $ Source[go/sql-injection] q5 := fmt.Sprintf("SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='%s' ORDER BY PRICE", RequestDataFromJson3.Category) - db.Query(q5) // NOT OK + db.Query(q5) // $ Alert[go/sql-injection] // NOT OK } diff --git a/go/ql/test/query-tests/Security/CWE-089/main.go b/go/ql/test/query-tests/Security/CWE-089/main.go index 7e5f5a35a9df..d0b17bf11459 100644 --- a/go/ql/test/query-tests/Security/CWE-089/main.go +++ b/go/ql/test/query-tests/Security/CWE-089/main.go @@ -8,12 +8,12 @@ import ( ) func test(db *sql.DB, r *http.Request) { - db.Query(r.Form["query"][0]) // NOT OK + db.Query(r.Form["query"][0]) // $ Alert[go/sql-injection] // NOT OK } func test2(tx *sql.Tx, r *http.Request) { - tx.Query(fmt.Sprintf("SELECT USER FROM USERS WHERE ID='%s'", r.URL.Query()["uuid"])) // NOT OK - tx.Query(fmt.Sprintf("SELECT USER FROM USERS WHERE ID='%s'", r.Header.Get("X-Uuid"))) // NOT OK + tx.Query(fmt.Sprintf("SELECT USER FROM USERS WHERE ID='%s'", r.URL.Query()["uuid"])) // $ Alert[go/sql-injection] // NOT OK + tx.Query(fmt.Sprintf("SELECT USER FROM USERS WHERE ID='%s'", r.Header.Get("X-Uuid"))) // $ Alert[go/sql-injection] // NOT OK } func main() {} @@ -27,39 +27,39 @@ type RequestStruct struct { func handler2(db *sql.DB, req *http.Request) { RequestData := &RequestStruct{ Id: 1, - Category: req.URL.Query()["category"], + Category: req.URL.Query()["category"], // $ Source[go/sql-injection] } q := fmt.Sprintf("SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='%s' ORDER BY PRICE", RequestData.Category) - db.Query(q) + db.Query(q) // $ Alert[go/sql-injection] } func handler3(db *sql.DB, req *http.Request) { RequestData := &RequestStruct{} - RequestData.Category = req.URL.Query()["category"] + RequestData.Category = req.URL.Query()["category"] // $ Source[go/sql-injection] q := fmt.Sprintf("SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='%s' ORDER BY PRICE", RequestData.Category) - db.Query(q) + db.Query(q) // $ Alert[go/sql-injection] } func handler4(db *sql.DB, req *http.Request) { RequestData := &RequestStruct{} - (*RequestData).Category = req.URL.Query()["category"] + (*RequestData).Category = req.URL.Query()["category"] // $ Source[go/sql-injection] q := fmt.Sprintf("SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='%s' ORDER BY PRICE", RequestData.Category) - db.Query(q) + db.Query(q) // $ Alert[go/sql-injection] } func handler5(db *sql.DB, req *http.Request) { RequestData := &RequestStruct{} - (*RequestData).Category = req.URL.Query()["category"] + (*RequestData).Category = req.URL.Query()["category"] // $ Source[go/sql-injection] q := fmt.Sprintf("SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='%s' ORDER BY PRICE", (*RequestData).Category) - db.Query(q) + db.Query(q) // $ Alert[go/sql-injection] } // This is an integer, so should not counted as injection diff --git a/go/ql/test/query-tests/Security/CWE-089/mongoDB.go b/go/ql/test/query-tests/Security/CWE-089/mongoDB.go index 818f8adb13cb..34c89d297b99 100644 --- a/go/ql/test/query-tests/Security/CWE-089/mongoDB.go +++ b/go/ql/test/query-tests/Security/CWE-089/mongoDB.go @@ -37,7 +37,7 @@ func mongo2(w http.ResponseWriter, r *http.Request) { // Get a handle for your collection db := client.Database("test") coll := db.Collection("collection") - untrustedInput := r.Referer() + untrustedInput := r.Referer() // $ Source[go/sql-injection] filter := bson.D{{"name", untrustedInput}} @@ -54,30 +54,30 @@ func mongo2(w http.ResponseWriter, r *http.Request) { update := bson.D{{"$inc", bson.D{{"age", 1}}}} // models := nil - coll.Aggregate(ctx, pipeline, nil) + coll.Aggregate(ctx, pipeline, nil) // $ Alert[go/sql-injection] // coll.BulkWrite(ctx, models, nil) coll.BulkWrite(ctx, nil, nil) coll.Clone(nil) - coll.CountDocuments(ctx, filter, nil) + coll.CountDocuments(ctx, filter, nil) // $ Alert[go/sql-injection] coll.Database() - coll.DeleteMany(ctx, filter, nil) - coll.DeleteOne(ctx, filter, nil) + coll.DeleteMany(ctx, filter, nil) // $ Alert[go/sql-injection] + coll.DeleteOne(ctx, filter, nil) // $ Alert[go/sql-injection] - coll.Distinct(ctx, fieldName, filter) + coll.Distinct(ctx, fieldName, filter) // $ Alert[go/sql-injection] coll.Drop(ctx) coll.EstimatedDocumentCount(ctx, nil) - coll.Find(ctx, filter, nil) - coll.FindOne(ctx, filter, nil) - coll.FindOneAndDelete(ctx, filter, nil) - coll.FindOneAndReplace(ctx, filter, nil) - coll.FindOneAndUpdate(ctx, filter, nil) + coll.Find(ctx, filter, nil) // $ Alert[go/sql-injection] + coll.FindOne(ctx, filter, nil) // $ Alert[go/sql-injection] + coll.FindOneAndDelete(ctx, filter, nil) // $ Alert[go/sql-injection] + coll.FindOneAndReplace(ctx, filter, nil) // $ Alert[go/sql-injection] + coll.FindOneAndUpdate(ctx, filter, nil) // $ Alert[go/sql-injection] coll.Indexes() coll.InsertMany(ctx, documents) coll.InsertOne(ctx, document, nil) coll.Name() - coll.ReplaceOne(ctx, filter, replacement) - coll.UpdateMany(ctx, filter, update) - coll.UpdateOne(ctx, filter, update) - coll.Watch(ctx, pipeline) + coll.ReplaceOne(ctx, filter, replacement) // $ Alert[go/sql-injection] + coll.UpdateMany(ctx, filter, update) // $ Alert[go/sql-injection] + coll.UpdateOne(ctx, filter, update) // $ Alert[go/sql-injection] + coll.Watch(ctx, pipeline) // $ Alert[go/sql-injection] } diff --git a/go/ql/test/query-tests/Security/CWE-190/AllocationSizeOverflow.go b/go/ql/test/query-tests/Security/CWE-190/AllocationSizeOverflow.go index aa11afa816aa..c717cf6fd710 100644 --- a/go/ql/test/query-tests/Security/CWE-190/AllocationSizeOverflow.go +++ b/go/ql/test/query-tests/Security/CWE-190/AllocationSizeOverflow.go @@ -3,11 +3,11 @@ package main import "encoding/json" func encryptValue(v interface{}) ([]byte, error) { - jsonData, err := json.Marshal(v) + jsonData, err := json.Marshal(v) // $ Source if err != nil { return nil, err } - size := len(jsonData) + (len(jsonData) % 16) + size := len(jsonData) + (len(jsonData) % 16) // $ Alert buffer := make([]byte, size) copy(buffer, jsonData) return encryptBuffer(buffer) diff --git a/go/ql/test/query-tests/Security/CWE-190/AllocationSizeOverflow.qlref b/go/ql/test/query-tests/Security/CWE-190/AllocationSizeOverflow.qlref index f6da9bc1c36d..e06f99c7747e 100644 --- a/go/ql/test/query-tests/Security/CWE-190/AllocationSizeOverflow.qlref +++ b/go/ql/test/query-tests/Security/CWE-190/AllocationSizeOverflow.qlref @@ -1,2 +1,4 @@ query: Security/CWE-190/AllocationSizeOverflow.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-190/tst.go b/go/ql/test/query-tests/Security/CWE-190/tst.go index abe4452343e2..6958fd9ad9ad 100644 --- a/go/ql/test/query-tests/Security/CWE-190/tst.go +++ b/go/ql/test/query-tests/Security/CWE-190/tst.go @@ -11,28 +11,28 @@ func test(x int, s string, xs []int, ys [16]int, ss [16]string, h *header) { jsonData, _ := json.Marshal(x) ignore(make([]byte, len(jsonData)+1)) // OK: data is small - jsonData, _ = json.Marshal(s) - ignore(make([]byte, len(jsonData)+1)) // NOT OK: data might be big + jsonData, _ = json.Marshal(s) // $ Source + ignore(make([]byte, len(jsonData)+1)) // $ Alert // NOT OK: data might be big jsonData, _ = json.Marshal("hi there") ignore(make([]byte, len(jsonData)+1)) // OK: data is small - jsonData, _ = json.Marshal(xs) - ignore(make([]byte, len(jsonData)+1)) // NOT OK: data might be big + jsonData, _ = json.Marshal(xs) // $ Source + ignore(make([]byte, len(jsonData)+1)) // $ Alert // NOT OK: data might be big jsonData, _ = json.Marshal(ys) ignore(make([]byte, len(jsonData)+1)) // OK: data is small - jsonData, _ = json.Marshal(ss) - ignore(make([]byte, 10, len(jsonData)+1)) // NOT OK: data might be big + jsonData, _ = json.Marshal(ss) // $ Source + ignore(make([]byte, 10, len(jsonData)+1)) // $ Alert // NOT OK: data might be big jsonData, _ = json.Marshal(h) ignore(make([]byte, len(jsonData)+1)) // OK: data is small var i interface{} i = h - jsonData, _ = json.Marshal(i) - ignore(make([]byte, len(jsonData)+1)) // NOT OK: data might be big + jsonData, _ = json.Marshal(i) // $ Source + ignore(make([]byte, len(jsonData)+1)) // $ Alert // NOT OK: data might be big } func ignore(_ interface{}) {} diff --git a/go/ql/test/query-tests/Security/CWE-190/tst2.go b/go/ql/test/query-tests/Security/CWE-190/tst2.go index d9dfe6912e81..28725266d965 100644 --- a/go/ql/test/query-tests/Security/CWE-190/tst2.go +++ b/go/ql/test/query-tests/Security/CWE-190/tst2.go @@ -6,13 +6,13 @@ import ( ) func test2(filename string) { - data, _ := ioutil.ReadFile(filename) - ignore(make([]byte, len(data)+1)) // NOT OK + data, _ := ioutil.ReadFile(filename) // $ Source + ignore(make([]byte, len(data)+1)) // $ Alert // NOT OK } func test3(r io.Reader) { - data, _ := ioutil.ReadAll(r) - ignore(make([]byte, len(data)+1)) // NOT OK + data, _ := ioutil.ReadAll(r) // $ Source + ignore(make([]byte, len(data)+1)) // $ Alert // NOT OK } func test4(r io.Reader, ws []io.Writer) { diff --git a/go/ql/test/query-tests/Security/CWE-190/tst3.go b/go/ql/test/query-tests/Security/CWE-190/tst3.go index 660345b099dd..9a9055639538 100644 --- a/go/ql/test/query-tests/Security/CWE-190/tst3.go +++ b/go/ql/test/query-tests/Security/CWE-190/tst3.go @@ -3,8 +3,8 @@ package main import "encoding/json" func testSanitizers(s string) { - jsonData, _ := json.Marshal(s) - ignore(make([]byte, len(jsonData)+1)) // NOT OK: data might be big + jsonData, _ := json.Marshal(s) // $ Source + ignore(make([]byte, len(jsonData)+1)) // $ Alert // NOT OK: data might be big ignore(make([]byte, int64(len(jsonData))+1)) // OK: sanitized by widening to 64 bits @@ -21,7 +21,7 @@ func testSanitizers(s string) { } { - newlength := len(jsonData) + 3 // NOT OK: newlength is changed after the upper bound check (even though it's made smaller) + newlength := len(jsonData) + 3 // $ Alert // NOT OK: newlength is changed after the upper bound check (even though it's made smaller) if newlength < 1000 { newlength = newlength - 1 ignore(make([]byte, newlength)) @@ -29,7 +29,7 @@ func testSanitizers(s string) { } { - newlength := len(jsonData) + 4 // NOT OK: there is an upper bound check but it doesn't dominate `make` + newlength := len(jsonData) + 4 // $ Alert // NOT OK: there is an upper bound check but it doesn't dominate `make` if newlength < 1000 { ignore(newlength + 2) } diff --git a/go/ql/test/query-tests/Security/CWE-209/StackTraceExposure.qlref b/go/ql/test/query-tests/Security/CWE-209/StackTraceExposure.qlref index 18cf2d49a1aa..420481918d12 100644 --- a/go/ql/test/query-tests/Security/CWE-209/StackTraceExposure.qlref +++ b/go/ql/test/query-tests/Security/CWE-209/StackTraceExposure.qlref @@ -1 +1,2 @@ -Security/CWE-209/StackTraceExposure.ql +query: Security/CWE-209/StackTraceExposure.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-209/test.go b/go/ql/test/query-tests/Security/CWE-209/test.go index 77df73b8046c..6a1b6c298ba2 100644 --- a/go/ql/test/query-tests/Security/CWE-209/test.go +++ b/go/ql/test/query-tests/Security/CWE-209/test.go @@ -12,10 +12,10 @@ var logger log.Logger func handlePanic(w http.ResponseWriter, r *http.Request) { buf := make([]byte, 2<<16) - stackLen := runtime.Stack(buf, true) + stackLen := runtime.Stack(buf, true) // $ Source buf = buf[:stackLen] // BAD: printing a stack trace back to the response - w.Write(buf) + w.Write(buf) // $ Alert // GOOD: logging the response to the server and sending // a more generic message. logger.Printf("Panic: %s", buf) diff --git a/go/ql/test/query-tests/Security/CWE-295/DisabledCertificateCheck/DisabledCertificateCheck.go b/go/ql/test/query-tests/Security/CWE-295/DisabledCertificateCheck/DisabledCertificateCheck.go index b0490ad6f4f2..67f757544f29 100644 --- a/go/ql/test/query-tests/Security/CWE-295/DisabledCertificateCheck/DisabledCertificateCheck.go +++ b/go/ql/test/query-tests/Security/CWE-295/DisabledCertificateCheck/DisabledCertificateCheck.go @@ -7,7 +7,7 @@ import ( func doAuthReq(authReq *http.Request) *http.Response { tr := &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // NOT OK + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // $ Alert // NOT OK } client := &http.Client{Transport: tr} res, _ := client.Do(authReq) diff --git a/go/ql/test/query-tests/Security/CWE-295/DisabledCertificateCheck/DisabledCertificateCheck.qlref b/go/ql/test/query-tests/Security/CWE-295/DisabledCertificateCheck/DisabledCertificateCheck.qlref index cca259717b57..8864221dea7c 100644 --- a/go/ql/test/query-tests/Security/CWE-295/DisabledCertificateCheck/DisabledCertificateCheck.qlref +++ b/go/ql/test/query-tests/Security/CWE-295/DisabledCertificateCheck/DisabledCertificateCheck.qlref @@ -1 +1,2 @@ -Security/CWE-295/DisabledCertificateCheck.ql +query: Security/CWE-295/DisabledCertificateCheck.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-295/DisabledCertificateCheck/main.go b/go/ql/test/query-tests/Security/CWE-295/DisabledCertificateCheck/main.go index 3cb5d107a70a..152ece5ba466 100644 --- a/go/ql/test/query-tests/Security/CWE-295/DisabledCertificateCheck/main.go +++ b/go/ql/test/query-tests/Security/CWE-295/DisabledCertificateCheck/main.go @@ -6,7 +6,7 @@ import ( ) func bad1(cfg *tls.Config) { - cfg.InsecureSkipVerify = true // NOT OK + cfg.InsecureSkipVerify = true // $ Alert // NOT OK } func good1(cfg *tls.Config) { @@ -54,12 +54,12 @@ func makeInsecureConfig() *tls.Config { } func makeConfig() *tls.Config { - return &tls.Config{InsecureSkipVerify: true} // NOT OK + return &tls.Config{InsecureSkipVerify: true} // $ Alert // NOT OK } func bad3() *http.Transport { transport := &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // NOT OK + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // $ Alert // NOT OK } return transport } diff --git a/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallback.expected b/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallback.expected index b81d24f26654..b05736dc4c4e 100644 --- a/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallback.expected +++ b/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallback.expected @@ -1,3 +1,8 @@ +#select +| InsecureHostKeyCallbackExample.go:15:20:18:5 | type conversion | InsecureHostKeyCallbackExample.go:16:4:18:4 | function literal | InsecureHostKeyCallbackExample.go:15:20:18:5 | type conversion | Configuring SSH ClientConfig with insecure HostKeyCallback implementation from $@. | InsecureHostKeyCallbackExample.go:16:4:18:4 | function literal | this source | +| InsecureHostKeyCallbackExample.go:26:20:26:46 | call to InsecureIgnoreHostKey | InsecureHostKeyCallbackExample.go:26:20:26:46 | call to InsecureIgnoreHostKey | InsecureHostKeyCallbackExample.go:26:20:26:46 | call to InsecureIgnoreHostKey | Configuring SSH ClientConfig with insecure HostKeyCallback implementation from $@. | InsecureHostKeyCallbackExample.go:26:20:26:46 | call to InsecureIgnoreHostKey | this source | +| InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | InsecureHostKeyCallbackExample.go:32:3:34:3 | function literal | InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | Configuring SSH ClientConfig with insecure HostKeyCallback implementation from $@. | InsecureHostKeyCallbackExample.go:32:3:34:3 | function literal | this source | +| InsecureHostKeyCallbackExample.go:52:20:52:48 | type conversion | InsecureHostKeyCallbackExample.go:45:3:47:3 | function literal | InsecureHostKeyCallbackExample.go:52:20:52:48 | type conversion | Configuring SSH ClientConfig with insecure HostKeyCallback implementation from $@. | InsecureHostKeyCallbackExample.go:45:3:47:3 | function literal | this source | edges | InsecureHostKeyCallbackExample.go:16:4:18:4 | function literal | InsecureHostKeyCallbackExample.go:15:20:18:5 | type conversion | provenance | | | InsecureHostKeyCallbackExample.go:31:14:34:4 | type conversion | InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | provenance | | @@ -41,8 +46,3 @@ nodes | InsecureHostKeyCallbackExample.go:118:35:118:61 | call to InsecureIgnoreHostKey | semmle.label | call to InsecureIgnoreHostKey | | InsecureHostKeyCallbackExample.go:120:44:120:68 | potentiallySecureCallback | semmle.label | potentiallySecureCallback | subpaths -#select -| InsecureHostKeyCallbackExample.go:15:20:18:5 | type conversion | InsecureHostKeyCallbackExample.go:16:4:18:4 | function literal | InsecureHostKeyCallbackExample.go:15:20:18:5 | type conversion | Configuring SSH ClientConfig with insecure HostKeyCallback implementation from $@. | InsecureHostKeyCallbackExample.go:16:4:18:4 | function literal | this source | -| InsecureHostKeyCallbackExample.go:26:20:26:46 | call to InsecureIgnoreHostKey | InsecureHostKeyCallbackExample.go:26:20:26:46 | call to InsecureIgnoreHostKey | InsecureHostKeyCallbackExample.go:26:20:26:46 | call to InsecureIgnoreHostKey | Configuring SSH ClientConfig with insecure HostKeyCallback implementation from $@. | InsecureHostKeyCallbackExample.go:26:20:26:46 | call to InsecureIgnoreHostKey | this source | -| InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | InsecureHostKeyCallbackExample.go:32:3:34:3 | function literal | InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | Configuring SSH ClientConfig with insecure HostKeyCallback implementation from $@. | InsecureHostKeyCallbackExample.go:32:3:34:3 | function literal | this source | -| InsecureHostKeyCallbackExample.go:52:20:52:48 | type conversion | InsecureHostKeyCallbackExample.go:45:3:47:3 | function literal | InsecureHostKeyCallbackExample.go:52:20:52:48 | type conversion | Configuring SSH ClientConfig with insecure HostKeyCallback implementation from $@. | InsecureHostKeyCallbackExample.go:45:3:47:3 | function literal | this source | diff --git a/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallback.qlref b/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallback.qlref index b5f8712594db..2c5cecd3a294 100644 --- a/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallback.qlref +++ b/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallback.qlref @@ -1 +1,2 @@ -Security/CWE-322/InsecureHostKeyCallback.ql +query: Security/CWE-322/InsecureHostKeyCallback.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallbackExample.go b/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallbackExample.go index d13bda30a5e4..1d5b17ebd8d4 100644 --- a/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallbackExample.go +++ b/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallbackExample.go @@ -15,7 +15,7 @@ func insecureSSHClientConfig() { HostKeyCallback: ssh.HostKeyCallback( // BAD func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil - }), + }), // $ Source Alert } } @@ -23,7 +23,7 @@ func insecureSSHClientConfigAlt() { _ = &ssh.ClientConfig{ User: "user", Auth: []ssh.AuthMethod{nil}, - HostKeyCallback: ssh.InsecureIgnoreHostKey(), // BAD + HostKeyCallback: ssh.InsecureIgnoreHostKey(), // $ Alert // BAD } } @@ -31,12 +31,12 @@ func insecureSSHClientConfigLocalFlow() { callback := ssh.HostKeyCallback( func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil - }) + }) // $ Source _ = &ssh.ClientConfig{ User: "user", Auth: []ssh.AuthMethod{nil}, - HostKeyCallback: callback, // BAD + HostKeyCallback: callback, // $ Alert // BAD } } @@ -44,12 +44,12 @@ func insecureSSHClientConfigLocalFlowAlt() { callback := func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil - } + } // $ Source _ = &ssh.ClientConfig{ User: "user", Auth: []ssh.AuthMethod{nil}, - HostKeyCallback: ssh.HostKeyCallback(callback), // BAD + HostKeyCallback: ssh.HostKeyCallback(callback), // $ Alert // BAD } } diff --git a/go/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.go b/go/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.go index 9d5ce2ac424f..6c28a054b654 100644 --- a/go/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.go +++ b/go/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.go @@ -6,16 +6,16 @@ import ( ) func foo1() { - rsa.GenerateKey(rand.Reader, 1024) // BAD + rsa.GenerateKey(rand.Reader, 1024) // $ Alert // BAD } func foo2() { - size := 1024 - rsa.GenerateKey(rand.Reader, size) // BAD + size := 1024 // $ Source + rsa.GenerateKey(rand.Reader, size) // $ Alert // BAD } func foo3() { - foo5(1024) // BAD + foo5(1024) // $ Source // BAD } func foo4() { @@ -23,13 +23,13 @@ func foo4() { } func foo5(size int) { - rsa.GenerateKey(rand.Reader, size) + rsa.GenerateKey(rand.Reader, size) // $ Alert } func foo6() { - keyBits := 1024 + keyBits := 1024 // $ Source if keyBits >= 2047 { - rsa.GenerateKey(rand.Reader, keyBits) // BAD + rsa.GenerateKey(rand.Reader, keyBits) // $ Alert // BAD } } @@ -41,10 +41,10 @@ func foo7() { } func foo8() { - keyBits := 1024 + keyBits := 1024 // $ Source switch { case keyBits >= 2047: - rsa.GenerateKey(rand.Reader, keyBits) // BAD + rsa.GenerateKey(rand.Reader, keyBits) // $ Alert // BAD } } @@ -58,13 +58,13 @@ func foo9() { func foo10(customOptionSupplied bool, nonConstantKeyBits int) { keyBits := 0 - constantKeyBits := 1024 + constantKeyBits := 1024 // $ Source if customOptionSupplied { keyBits = constantKeyBits } else { keyBits = nonConstantKeyBits } - rsa.GenerateKey(rand.Reader, keyBits) // BAD + rsa.GenerateKey(rand.Reader, keyBits) // $ Alert // BAD } func foo11(customOptionSupplied bool, nonConstantKeyBits int) { diff --git a/go/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.qlref b/go/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.qlref index fbb59dd4be63..ef999cf368a5 100644 --- a/go/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.qlref +++ b/go/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.qlref @@ -1 +1,2 @@ -Security/CWE-326/InsufficientKeySize.ql +query: Security/CWE-326/InsufficientKeySize.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-327/UnsafeTLS.go b/go/ql/test/query-tests/Security/CWE-327/UnsafeTLS.go index 24dfeb195a04..5a91077e5559 100644 --- a/go/ql/test/query-tests/Security/CWE-327/UnsafeTLS.go +++ b/go/ql/test/query-tests/Security/CWE-327/UnsafeTLS.go @@ -18,7 +18,7 @@ func oldVersionFunc() bool { func minMaxTlsVersion() { { config := &tls.Config{} - config.MinVersion = 0 // BAD + config.MinVersion = 0 // $ Alert[go/insecure-tls] // BAD } { config := &tls.Config{} @@ -27,7 +27,7 @@ func minMaxTlsVersion() { /// { config := &tls.Config{ - MinVersion: 0, // BAD + MinVersion: 0, // $ Alert[go/insecure-tls] // BAD } _ = config } @@ -40,40 +40,40 @@ func minMaxTlsVersion() { /// { config := &tls.Config{} - config.MinVersion = tls.VersionSSL30 // BAD + config.MinVersion = tls.VersionSSL30 // $ Alert[go/insecure-tls] // BAD } { config := &tls.Config{} - config.MaxVersion = tls.VersionSSL30 // BAD + config.MaxVersion = tls.VersionSSL30 // $ Alert[go/insecure-tls] // BAD } /// { config := &tls.Config{} - config.MinVersion = tls.VersionTLS10 // BAD + config.MinVersion = tls.VersionTLS10 // $ Alert[go/insecure-tls] // BAD } { config := &tls.Config{} - config.MaxVersion = tls.VersionTLS10 // BAD + config.MaxVersion = tls.VersionTLS10 // $ Alert[go/insecure-tls] // BAD } /// { config := &tls.Config{} - config.MinVersion = tls.VersionTLS11 // BAD + config.MinVersion = tls.VersionTLS11 // $ Alert[go/insecure-tls] // BAD } { config := &tls.Config{} - config.MaxVersion = tls.VersionTLS11 // BAD + config.MaxVersion = tls.VersionTLS11 // $ Alert[go/insecure-tls] // BAD } /// { config := &tls.Config{ - MinVersion: tls.VersionTLS11, // BAD + MinVersion: tls.VersionTLS11, // $ Alert[go/insecure-tls] // BAD } _ = config } { config := &tls.Config{ - MaxVersion: tls.VersionTLS11, // BAD + MaxVersion: tls.VersionTLS11, // $ Alert[go/insecure-tls] // BAD } _ = config } @@ -92,13 +92,13 @@ func minMaxTlsVersion() { /// { config := &tls.Config{ - MinVersion: 0x0300, // BAD + MinVersion: 0x0300, // $ Alert[go/insecure-tls] // BAD } _ = config } { config := &tls.Config{ - MaxVersion: 0x0301, // BAD + MaxVersion: 0x0301, // $ Alert[go/insecure-tls] // BAD } _ = config } @@ -108,7 +108,7 @@ func minMaxTlsVersion() { oldVersionFlag := len(os.Args) > 3 if unknown { config := &tls.Config{ - MinVersion: 0, // BAD + MinVersion: 0, // $ Alert[go/insecure-tls] // BAD } _ = config } @@ -198,7 +198,7 @@ func minMaxTlsVersion() { _ = config default: config := &tls.Config{ - MinVersion: 0, // BAD + MinVersion: 0, // $ Alert[go/insecure-tls] // BAD } _ = config } @@ -216,7 +216,7 @@ func minMaxTlsVersion() { _ = config default: config := &tls.Config{ - MinVersion: 0, // BAD + MinVersion: 0, // $ Alert[go/insecure-tls] // BAD } _ = config } @@ -257,61 +257,61 @@ func cipherSuites() { { config := &tls.Config{ CipherSuites: []uint16{ - tls.TLS_RSA_WITH_RC4_128_SHA, // BAD - tls.TLS_RSA_WITH_AES_128_CBC_SHA256, // BAD - tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, // BAD - tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA, // BAD - tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, // BAD - tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, // BAD - }, + tls.TLS_RSA_WITH_RC4_128_SHA, // $ Source[go/insecure-tls] // BAD + tls.TLS_RSA_WITH_AES_128_CBC_SHA256, // $ Source[go/insecure-tls] // BAD + tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, // $ Source[go/insecure-tls] // BAD + tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA, // $ Source[go/insecure-tls] // BAD + tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, // $ Source[go/insecure-tls] // BAD + tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, // $ Source[go/insecure-tls] // BAD + }, // $ Alert[go/insecure-tls] } _ = config } { config := &tls.Config{ CipherSuites: []uint16{ - tls.TLS_RSA_WITH_RC4_128_SHA, // BAD - }, + tls.TLS_RSA_WITH_RC4_128_SHA, // $ Source[go/insecure-tls] // BAD + }, // $ Alert[go/insecure-tls] } _ = config } { config := &tls.Config{ CipherSuites: []uint16{ - tls.TLS_RSA_WITH_AES_128_CBC_SHA256, // BAD - }, + tls.TLS_RSA_WITH_AES_128_CBC_SHA256, // $ Source[go/insecure-tls] // BAD + }, // $ Alert[go/insecure-tls] } _ = config } { config := &tls.Config{ CipherSuites: []uint16{ - tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, // BAD - }, + tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, // $ Source[go/insecure-tls] // BAD + }, // $ Alert[go/insecure-tls] } _ = config } { config := &tls.Config{ CipherSuites: []uint16{ - tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA, // BAD - }, + tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA, // $ Source[go/insecure-tls] // BAD + }, // $ Alert[go/insecure-tls] } _ = config } { config := &tls.Config{ CipherSuites: []uint16{ - tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, // BAD - }, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, // $ Source[go/insecure-tls] // BAD + }, // $ Alert[go/insecure-tls] } _ = config } { config := &tls.Config{ CipherSuites: []uint16{ - tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, // BAD - }, + tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, // $ Source[go/insecure-tls] // BAD + }, // $ Alert[go/insecure-tls] } _ = config } @@ -326,33 +326,33 @@ func cipherSuites() { { config := &tls.Config{} config.CipherSuites = make([]uint16, 0) - config.CipherSuites = append(config.CipherSuites, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) // BAD + config.CipherSuites = append(config.CipherSuites, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) // $ Alert[go/insecure-tls] // BAD } { config := &tls.Config{} config.CipherSuites = make([]uint16, 0) - suites := tls.InsecureCipherSuites() + suites := tls.InsecureCipherSuites() // $ Source[go/insecure-tls] for _, v := range suites { - config.CipherSuites = append(config.CipherSuites, v.ID) // BAD + config.CipherSuites = append(config.CipherSuites, v.ID) // $ Alert[go/insecure-tls] // BAD } } { config := &tls.Config{} cipherSuites := make([]uint16, 0) - suites := tls.InsecureCipherSuites() + suites := tls.InsecureCipherSuites() // $ Source[go/insecure-tls] for _, v := range suites { cipherSuites = append(cipherSuites, v.ID) } - config.CipherSuites = cipherSuites // BAD + config.CipherSuites = cipherSuites // $ Alert[go/insecure-tls] // BAD } { config := &tls.Config{} cipherSuites := make([]uint16, 0) - suites := tls.InsecureCipherSuites() + suites := tls.InsecureCipherSuites() // $ Source[go/insecure-tls] for i := range suites { cipherSuites = append(cipherSuites, suites[i].ID) } - config.CipherSuites = cipherSuites // BAD + config.CipherSuites = cipherSuites // $ Alert[go/insecure-tls] // BAD } unknown := len(os.Args) > 1 insecureFlag := len(os.Args) > 2 @@ -360,8 +360,8 @@ func cipherSuites() { if unknown { config := &tls.Config{ CipherSuites: []uint16{ - tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, // BAD - }, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, // $ Source[go/insecure-tls] // BAD + }, // $ Alert[go/insecure-tls] } _ = config } @@ -430,8 +430,8 @@ func cipherSuites() { default: config := &tls.Config{ CipherSuites: []uint16{ - tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, // BAD - }, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, // $ Source[go/insecure-tls] // BAD + }, // $ Alert[go/insecure-tls] } _ = config } @@ -454,8 +454,8 @@ func cipherSuites() { default: config := &tls.Config{ CipherSuites: []uint16{ - tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, // BAD - }, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, // $ Source[go/insecure-tls] // BAD + }, // $ Alert[go/insecure-tls] } _ = config } diff --git a/go/ql/test/query-tests/Security/CWE-327/UnsafeTLS.qlref b/go/ql/test/query-tests/Security/CWE-327/UnsafeTLS.qlref index 0349f62f26fa..892cb53d05bb 100644 --- a/go/ql/test/query-tests/Security/CWE-327/UnsafeTLS.qlref +++ b/go/ql/test/query-tests/Security/CWE-327/UnsafeTLS.qlref @@ -1,2 +1,4 @@ query: Security/CWE-327/InsecureTLS.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.go b/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.go index 2e4d309f46c6..0dbc48b19d18 100644 --- a/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.go +++ b/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.go @@ -9,7 +9,7 @@ var charset = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345 func generatePassword() string { s := make([]rune, 20) for i := range s { - s[i] = charset[rand.Intn(len(charset))] // BAD: weak RNG used to generate password + s[i] = charset[rand.Intn(len(charset))] // $ Alert // BAD: weak RNG used to generate password } return string(s) } diff --git a/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.qlref b/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.qlref index b30e6ede8ceb..f148404a1c5e 100644 --- a/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.qlref +++ b/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.qlref @@ -1,2 +1,4 @@ query: Security/CWE-338/InsecureRandomness.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/sample.go b/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/sample.go index 9eef81f63bb4..3edbb67c42df 100644 --- a/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/sample.go +++ b/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/sample.go @@ -12,7 +12,7 @@ import ( ) func Guid() []byte { - hash := sha256.Sum256([]byte(fmt.Sprintf("%n", rand.Uint32()))) // OK: may not be used in a cryptographic setting + hash := sha256.Sum256([]byte(fmt.Sprintf("%n", rand.Uint32()))) // $ Source // OK: may not be used in a cryptographic setting return hash[:] } @@ -23,7 +23,7 @@ func createHash(key string) string { } func ed25519FromGuid() { - ed25519.NewKeyFromSeed(Guid()) // BAD: Guid internally uses rand + ed25519.NewKeyFromSeed(Guid()) // $ Alert // BAD: Guid internally uses rand } func encrypt(data []byte, password string) []byte { @@ -31,16 +31,16 @@ func encrypt(data []byte, password string) []byte { gcm, _ := cipher.NewGCM(block) nonce := make([]byte, gcm.NonceSize()) - random := rand.New(rand.NewSource(999)) + random := rand.New(rand.NewSource(999)) // $ Source io.ReadFull(random, nonce) - ciphertext := gcm.Seal(data[:0], nonce, data, nil) // BAD: use of an insecure rng to generate a nonce + ciphertext := gcm.Seal(data[:0], nonce, data, nil) // $ Alert // BAD: use of an insecure rng to generate a nonce return ciphertext } func makePasswordFiveChar() string { s := make([]rune, 5) - s[0] = charset[rand.Intn(len(charset))] // BAD: weak RNG used to generate salt + s[0] = charset[rand.Intn(len(charset))] // $ Alert // BAD: weak RNG used to generate salt s[1] = charset[rand.Intn(len(charset))] // Rest OK because only the first result is caught s[2] = charset[rand.Intn(len(charset))] s[3] = charset[rand.Intn(len(charset))] @@ -52,8 +52,8 @@ func generateRandomKey() ed25519.PrivateKey { candidates := "0123456789ABCDEF" seed := "" for i := 0; i < ed25519.SeedSize; i++ { - randNumber := rand.Intn(len(candidates)) + randNumber := rand.Intn(len(candidates)) // $ Source seed += string(candidates[randNumber]) } - return ed25519.NewKeyFromSeed([]byte(seed)) // BAD: seed candidates were selected with a weak RNG + return ed25519.NewKeyFromSeed([]byte(seed)) // $ Alert // BAD: seed candidates were selected with a weak RNG } diff --git a/go/ql/test/query-tests/Security/CWE-347/MissingJwtSignatureCheck.qlref b/go/ql/test/query-tests/Security/CWE-347/MissingJwtSignatureCheck.qlref index 404fe618edc8..55524e6e0e62 100644 --- a/go/ql/test/query-tests/Security/CWE-347/MissingJwtSignatureCheck.qlref +++ b/go/ql/test/query-tests/Security/CWE-347/MissingJwtSignatureCheck.qlref @@ -1,2 +1,4 @@ query: Security/CWE-347/MissingJwtSignatureCheck.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-347/go-jose.v3.go b/go/ql/test/query-tests/Security/CWE-347/go-jose.v3.go index 3e55ced31f6a..67ce9ed00ea9 100644 --- a/go/ql/test/query-tests/Security/CWE-347/go-jose.v3.go +++ b/go/ql/test/query-tests/Security/CWE-347/go-jose.v3.go @@ -22,7 +22,7 @@ func jose(r *http.Request) { verifyJWT(signedToken) // NOT OK: no verification - signedToken = r.URL.Query().Get("signedToken") + signedToken = r.URL.Query().Get("signedToken") // $ Source notVerifyJWT(signedToken) } @@ -30,7 +30,7 @@ func notVerifyJWT(signedToken string) { fmt.Println("only decoding JWT") DecodedToken, _ := jwt.ParseSigned(signedToken) out := CustomerInfo{} - if err := DecodedToken.UnsafeClaimsWithoutVerification(&out); err != nil { + if err := DecodedToken.UnsafeClaimsWithoutVerification(&out); err != nil { // $ Alert panic(err) } fmt.Printf("%v\n", out) diff --git a/go/ql/test/query-tests/Security/CWE-347/golang-jwt-v5.go b/go/ql/test/query-tests/Security/CWE-347/golang-jwt-v5.go index e37265f03c04..82d6c7647973 100644 --- a/go/ql/test/query-tests/Security/CWE-347/golang-jwt-v5.go +++ b/go/ql/test/query-tests/Security/CWE-347/golang-jwt-v5.go @@ -25,13 +25,13 @@ func golangjwt(r *http.Request) { verifyJWT_golangjwt(signedToken) // NOT OK: only unverified parse - signedToken = r.URL.Query().Get("signedToken") + signedToken = r.URL.Query().Get("signedToken") // $ Source notVerifyJWT_golangjwt(signedToken) } func notVerifyJWT_golangjwt(signedToken string) { fmt.Println("only decoding JWT") - DecodedToken, _, err := jwt.NewParser().ParseUnverified(signedToken, &CustomerInfo1{}) + DecodedToken, _, err := jwt.NewParser().ParseUnverified(signedToken, &CustomerInfo1{}) // $ Alert if claims, ok := DecodedToken.Claims.(*CustomerInfo1); ok { fmt.Printf("DecodedToken:%v\n", claims) } else { diff --git a/go/ql/test/query-tests/Security/CWE-352/ConstantOauth2State.go b/go/ql/test/query-tests/Security/CWE-352/ConstantOauth2State.go index 75f899aea518..817c76c8bfa9 100644 --- a/go/ql/test/query-tests/Security/CWE-352/ConstantOauth2State.go +++ b/go/ql/test/query-tests/Security/CWE-352/ConstantOauth2State.go @@ -17,9 +17,9 @@ import ( func main() {} -const stateStringConst = "state" +const stateStringConst = "state" // $ Source -var stateStringVar = "state" +var stateStringVar = "state" // $ Source func badWithStringLiteralState(w http.ResponseWriter) { conf := &oauth2.Config{ @@ -32,7 +32,7 @@ func badWithStringLiteralState(w http.ResponseWriter) { }, } - url := conf.AuthCodeURL("state") // BAD + url := conf.AuthCodeURL("state") // $ Alert // BAD _ = url // ... } @@ -47,7 +47,7 @@ func badWithConstState(w http.ResponseWriter) { }, } - url := conf.AuthCodeURL(stateStringConst) // BAD + url := conf.AuthCodeURL(stateStringConst) // $ Alert // BAD _ = url // ... } @@ -62,7 +62,7 @@ func badWithFixedVarState(w http.ResponseWriter) { }, } - url := conf.AuthCodeURL(stateStringVar) // BAD + url := conf.AuthCodeURL(stateStringVar) // $ Alert // BAD _ = url // ... } @@ -78,12 +78,12 @@ func badWithFixedStateReturned(w http.ResponseWriter) { } state := newFixedState() - url := conf.AuthCodeURL(state) // BAD + url := conf.AuthCodeURL(state) // $ Alert // BAD _ = url // ... } func newFixedState() string { - return "state" + return "state" // $ Source } func betterWithVariableStateReturned(w http.ResponseWriter) { @@ -229,7 +229,7 @@ func badWithConstStatePrinter(w http.ResponseWriter) { }, } - url := conf.AuthCodeURL(stateStringConst) // BAD + url := conf.AuthCodeURL(stateStringConst) // $ Alert // BAD fmt.Printf("LOG: URL %v", url) // ... } diff --git a/go/ql/test/query-tests/Security/CWE-352/ConstantOauth2State.qlref b/go/ql/test/query-tests/Security/CWE-352/ConstantOauth2State.qlref index 7898f39d4155..7d6cf6469157 100644 --- a/go/ql/test/query-tests/Security/CWE-352/ConstantOauth2State.qlref +++ b/go/ql/test/query-tests/Security/CWE-352/ConstantOauth2State.qlref @@ -1 +1,2 @@ -Security/CWE-352/ConstantOauth2State.ql +query: Security/CWE-352/ConstantOauth2State.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.go b/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.go index 279e59c9cfbc..74e7c7c1c33e 100644 --- a/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.go +++ b/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.go @@ -1,7 +1,7 @@ package main -func sanitizeUrl(redir string) string { - if len(redir) > 0 && redir[0] == '/' { +func sanitizeUrl(redir string) string { // $ Source + if len(redir) > 0 && redir[0] == '/' { // $ Alert return redir } return "/" diff --git a/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.qlref b/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.qlref index fddee377510d..59540d49a15e 100644 --- a/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.qlref +++ b/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.qlref @@ -1,2 +1,4 @@ query: Security/CWE-601/BadRedirectCheck.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/cves.go b/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/cves.go index 42e8bab3452f..01fc6553977e 100644 --- a/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/cves.go +++ b/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/cves.go @@ -8,12 +8,12 @@ import ( // CVE-2018-15178 // Code from github.com/gogs/gogs func isValidRedirect(url string) bool { - return len(url) >= 2 && url[0] == '/' && url[1] != '/' // NOT OK + return len(url) >= 2 && url[0] == '/' && url[1] != '/' // $ Alert // NOT OK } -func alsoABadRedirect(url string, rw http.ResponseWriter, req *http.Request) { +func alsoABadRedirect(url string, rw http.ResponseWriter, req *http.Request) { // $ Source if isValidRedirect(url) { - http.Redirect(rw, req, url, 302) + http.Redirect(rw, req, url, 302) // $ Sink } } @@ -30,17 +30,17 @@ func alsoAGoodRedirect(url string, rw http.ResponseWriter, req *http.Request) { // CVE-2017-1000070 (both vulnerable!) // Code from github.com/bitly/oauth2_proxy func OAuthCallback(rw http.ResponseWriter, req *http.Request) { - redirect := req.Form.Get("state") - if !strings.HasPrefix(redirect, "/") { // NOT OK + redirect := req.Form.Get("state") // $ Source + if !strings.HasPrefix(redirect, "/") { // $ Alert // NOT OK redirect = "/" } - http.Redirect(rw, req, redirect, 302) + http.Redirect(rw, req, redirect, 302) // $ Sink } func OAuthCallback1(rw http.ResponseWriter, req *http.Request) { - redirect := req.Form.Get("state") - if !strings.HasPrefix(redirect, "/") || strings.HasPrefix(redirect, "//") { // NOT OK + redirect := req.Form.Get("state") // $ Source + if !strings.HasPrefix(redirect, "/") || strings.HasPrefix(redirect, "//") { // $ Alert // NOT OK redirect = "/" } - http.Redirect(rw, req, redirect, 302) + http.Redirect(rw, req, redirect, 302) // $ Sink } diff --git a/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/main.go b/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/main.go index beccc9a135d0..f45653e0945e 100644 --- a/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/main.go +++ b/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/main.go @@ -7,8 +7,8 @@ import ( "strings" ) -func badRedirect(redirect string, rw http.ResponseWriter, req *http.Request) { - http.Redirect(rw, req, sanitizeUrl(redirect), 302) +func badRedirect(redirect string, rw http.ResponseWriter, req *http.Request) { // $ Source + http.Redirect(rw, req, sanitizeUrl(redirect), 302) // $ Sink } func goodRedirect(redirect string, rw http.ResponseWriter, req *http.Request) { @@ -22,16 +22,16 @@ func goodRedirect2(url string, rw http.ResponseWriter, req *http.Request) { func isValidRedir(redirect string) bool { switch { // Not OK: does not check for '/\' - case strings.HasPrefix(redirect, "/") && !strings.HasPrefix(redirect, "//"): + case strings.HasPrefix(redirect, "/") && !strings.HasPrefix(redirect, "//"): // $ Alert return true default: return false } } -func alsoABadRedirect1(url string, rw http.ResponseWriter, req *http.Request) { +func alsoABadRedirect1(url string, rw http.ResponseWriter, req *http.Request) { // $ Source if isValidRedir(url) { - http.Redirect(rw, req, url, 302) + http.Redirect(rw, req, url, 302) // $ Sink } } @@ -65,28 +65,28 @@ func goodRedirect4(url string, rw http.ResponseWriter, req *http.Request) { http.Redirect(rw, req, getTarget(url), 302) } -func getTarget1(redirect string) string { - if redirect[0] != '/' { +func getTarget1(redirect string) string { // $ Source + if redirect[0] != '/' { // $ Alert return "/" } return path.Clean(redirect) } -func badRedirect1(url string, rw http.ResponseWriter, req *http.Request) { - http.Redirect(rw, req, getTarget1(url), 302) +func badRedirect1(url string, rw http.ResponseWriter, req *http.Request) { // $ Source + http.Redirect(rw, req, getTarget1(url), 302) // $ Sink } func getTarget2(redirect string) string { u, _ := url.Parse(redirect) - if u.Path[0] != '/' { + if u.Path[0] != '/' { // $ Alert return "/" } - return u.Path + return u.Path // $ Source } func badRedirect2(url string, rw http.ResponseWriter, req *http.Request) { - http.Redirect(rw, req, getTarget2(url), 302) + http.Redirect(rw, req, getTarget2(url), 302) // $ Sink } diff --git a/go/ql/test/query-tests/Security/CWE-643/XPathInjection.go b/go/ql/test/query-tests/Security/CWE-643/XPathInjection.go index 50b130db91c0..bb7a45ca99a4 100644 --- a/go/ql/test/query-tests/Security/CWE-643/XPathInjection.go +++ b/go/ql/test/query-tests/Security/CWE-643/XPathInjection.go @@ -10,10 +10,10 @@ import ( func processRequest(r *http.Request, doc tree.Node) { r.ParseForm() - username := r.Form.Get("username") + username := r.Form.Get("username") // $ Source // BAD: User input used directly in an XPath expression - xPath := goxpath.MustParse("//users/user[login/text()='" + username + "']/home_dir/text()") + xPath := goxpath.MustParse("//users/user[login/text()='" + username + "']/home_dir/text()") // $ Alert unsafeRes, _ := xPath.ExecBool(doc) fmt.Println(unsafeRes) diff --git a/go/ql/test/query-tests/Security/CWE-643/XPathInjection.qlref b/go/ql/test/query-tests/Security/CWE-643/XPathInjection.qlref index e6a07d4a6886..f3d92cc4c017 100644 --- a/go/ql/test/query-tests/Security/CWE-643/XPathInjection.qlref +++ b/go/ql/test/query-tests/Security/CWE-643/XPathInjection.qlref @@ -1,2 +1,4 @@ query: Security/CWE-643/XPathInjection.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-643/tst.go b/go/ql/test/query-tests/Security/CWE-643/tst.go index d3fc98b41a78..cf15ceeb0334 100644 --- a/go/ql/test/query-tests/Security/CWE-643/tst.go +++ b/go/ql/test/query-tests/Security/CWE-643/tst.go @@ -32,70 +32,70 @@ func main() {} func testAntchfxXpath(r *http.Request) { r.ParseForm() - username := r.Form.Get("username") + username := r.Form.Get("username") // $ Source // BAD: User input used directly in an XPath expression - _, _ = xpath.Compile("//users/user[login/text()='" + username + "']/home_dir/text()") - _, _ = xpath.CompileWithNS("//users/user[login/text()='"+username+"']/home_dir/text()", make(map[string]string)) - _ = xpath.MustCompile("//users/user[login/text()='" + username + "']/home_dir/text()") - _ = xpath.Select(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") + _, _ = xpath.Compile("//users/user[login/text()='" + username + "']/home_dir/text()") // $ Alert + _, _ = xpath.CompileWithNS("//users/user[login/text()='"+username+"']/home_dir/text()", make(map[string]string)) // $ Alert + _ = xpath.MustCompile("//users/user[login/text()='" + username + "']/home_dir/text()") // $ Alert + _ = xpath.Select(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") // $ Alert } func testAntchfxHtmlquery(r *http.Request) { r.ParseForm() - username := r.Form.Get("username") + username := r.Form.Get("username") // $ Source // BAD: User input used directly in an XPath expression - _ = htmlquery.Find(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") - _ = htmlquery.FindOne(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") - _, _ = htmlquery.Query(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") - _, _ = htmlquery.QueryAll(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") + _ = htmlquery.Find(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") // $ Alert + _ = htmlquery.FindOne(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") // $ Alert + _, _ = htmlquery.Query(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") // $ Alert + _, _ = htmlquery.QueryAll(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") // $ Alert } func testAntchfxXmlquery(r *http.Request, n *xmlquery.Node) { r.ParseForm() - username := r.Form.Get("username") + username := r.Form.Get("username") // $ Source // BAD: User input used directly in an XPath expression - _ = xmlquery.Find(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") - _ = xmlquery.FindOne(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") - xmlquery.FindEach(nil, "//users/user[login/text()='"+username+"']/home_dir/text()", nil) - xmlquery.FindEachWithBreak(nil, "//users/user[login/text()='"+username+"']/home_dir/text()", nil) - _, _ = xmlquery.Query(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") - _, _ = xmlquery.QueryAll(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") - _ = n.SelectElements("//users/user[login/text()='" + username + "']/home_dir/text()") - _ = n.SelectElement("//users/user[login/text()='" + username + "']/home_dir/text()") + _ = xmlquery.Find(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") // $ Alert + _ = xmlquery.FindOne(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") // $ Alert + xmlquery.FindEach(nil, "//users/user[login/text()='"+username+"']/home_dir/text()", nil) // $ Alert + xmlquery.FindEachWithBreak(nil, "//users/user[login/text()='"+username+"']/home_dir/text()", nil) // $ Alert + _, _ = xmlquery.Query(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") // $ Alert + _, _ = xmlquery.QueryAll(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") // $ Alert + _ = n.SelectElements("//users/user[login/text()='" + username + "']/home_dir/text()") // $ Alert + _ = n.SelectElement("//users/user[login/text()='" + username + "']/home_dir/text()") // $ Alert } func testAntchfxJsonquery(r *http.Request) { r.ParseForm() - username := r.Form.Get("username") + username := r.Form.Get("username") // $ Source // BAD: User input used directly in an XPath expression - _ = jsonquery.Find(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") - _ = jsonquery.FindOne(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") - _, _ = jsonquery.Query(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") - _, _ = jsonquery.QueryAll(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") + _ = jsonquery.Find(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") // $ Alert + _ = jsonquery.FindOne(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") // $ Alert + _, _ = jsonquery.Query(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") // $ Alert + _, _ = jsonquery.QueryAll(nil, "//users/user[login/text()='"+username+"']/home_dir/text()") // $ Alert } func testGoXmlpathXmlpath(r *http.Request) { r.ParseForm() - username := r.Form.Get("username") + username := r.Form.Get("username") // $ Source // BAD: User input used directly in an XPath expression - _, _ = xmlpath.Compile("//users/user[login/text()='" + username + "']/home_dir/text()") - _ = xmlpath.MustCompile("//users/user[login/text()='" + username + "']/home_dir/text()") + _, _ = xmlpath.Compile("//users/user[login/text()='" + username + "']/home_dir/text()") // $ Alert + _ = xmlpath.MustCompile("//users/user[login/text()='" + username + "']/home_dir/text()") // $ Alert } func testChrisTrenkampGoxpath(r *http.Request) { r.ParseForm() - username := r.Form.Get("username") - password := r.Form.Get("password") + username := r.Form.Get("username") // $ Source + password := r.Form.Get("password") // $ Source // BAD: User input used directly in an XPath expression - _, _ = goxpath.Parse("//users/user[login/text()='" + username + "' and password/text() = '" + password + "']/home_dir/text()") - _ = goxpath.MustParse("//users/user[login/text()='" + username + "' and password/text() = '" + password + "']/home_dir/text()") - _, _ = goxpath.ParseExec("//users/user[login/text()='"+username+"' and password/text() = '"+password+"']/home_dir/text()", nil) + _, _ = goxpath.Parse("//users/user[login/text()='" + username + "' and password/text() = '" + password + "']/home_dir/text()") // $ Alert + _ = goxpath.MustParse("//users/user[login/text()='" + username + "' and password/text() = '" + password + "']/home_dir/text()") // $ Alert + _, _ = goxpath.ParseExec("//users/user[login/text()='"+username+"' and password/text() = '"+password+"']/home_dir/text()", nil) // $ Alert // GOOD: Uses parameters to avoid including user input directly in XPath expression _ = goxpath.MustParse("//users/user[login/text()=$username and password/text() = $password]/home_dir/text()") @@ -103,24 +103,24 @@ func testChrisTrenkampGoxpath(r *http.Request) { func testSanthoshTekuriXpathparser(r *http.Request) { r.ParseForm() - username := r.Form.Get("username") + username := r.Form.Get("username") // $ Source // BAD: User input used directly in an XPath expression - _, _ = xpathparser.Parse("//users/user[login/text()='" + username + "']/home_dir/text()") - _ = xpathparser.MustParse("//users/user[login/text()='" + username + "']/home_dir/text()") + _, _ = xpathparser.Parse("//users/user[login/text()='" + username + "']/home_dir/text()") // $ Alert + _ = xpathparser.MustParse("//users/user[login/text()='" + username + "']/home_dir/text()") // $ Alert } func testJbowtieGokogiri(r *http.Request, n gokogiriXml.Node) { r.ParseForm() - username := r.Form.Get("username") - password := r.Form.Get("password") + username := r.Form.Get("username") // $ Source + password := r.Form.Get("password") // $ Source // BAD: User input used directly in an XPath expression - xpath := gokogiriXpath.Compile("//users/user[login/text()='" + username + "' and password/text() = '" + password + "']/home_dir/text()") - _, _ = n.Search("//users/user[login/text()='" + username + "' and password/text() = '" + password + "']/home_dir/text()") - _, _ = n.SearchWithVariables("//users/user[login/text()='"+username+"' and password/text() = '"+password+"']/home_dir/text()", nil) - _, _ = n.EvalXPath("//users/user[login/text()='"+username+"' and password/text() = '"+password+"']/home_dir/text()", nil) - _ = n.EvalXPathAsBoolean("//users/user[login/text()='"+username+"' and password/text() = '"+password+"']/home_dir/text()", nil) + xpath := gokogiriXpath.Compile("//users/user[login/text()='" + username + "' and password/text() = '" + password + "']/home_dir/text()") // $ Alert + _, _ = n.Search("//users/user[login/text()='" + username + "' and password/text() = '" + password + "']/home_dir/text()") // $ Alert + _, _ = n.SearchWithVariables("//users/user[login/text()='"+username+"' and password/text() = '"+password+"']/home_dir/text()", nil) // $ Alert + _, _ = n.EvalXPath("//users/user[login/text()='"+username+"' and password/text() = '"+password+"']/home_dir/text()", nil) // $ Alert + _ = n.EvalXPathAsBoolean("//users/user[login/text()='"+username+"' and password/text() = '"+password+"']/home_dir/text()", nil) // $ Alert // OK: Not flagged, since the creation of `xpath` is already flagged. _, _ = n.Search(xpath) @@ -136,12 +136,12 @@ func testJbowtieGokogiri(r *http.Request, n gokogiriXml.Node) { func testLestratGoLibxml2(r *http.Request) { r.ParseForm() - username := r.Form.Get("username") + username := r.Form.Get("username") // $ Source p := parser.New(parser.XMLParseNoEnt) // BAD: User input used directly in an XPath expression - _, _ = p.Parse([]byte("//users/user[login/text()='" + username + "']/home_dir/text()")) + _, _ = p.Parse([]byte("//users/user[login/text()='" + username + "']/home_dir/text()")) // $ Alert _, _ = p.ParseReader(strings.NewReader("//users/user[login/text()='" + username + "']/home_dir/text()")) - _, _ = p.ParseString("//users/user[login/text()='" + username + "']/home_dir/text()") + _, _ = p.ParseString("//users/user[login/text()='" + username + "']/home_dir/text()") // $ Alert } diff --git a/go/ql/test/query-tests/Security/CWE-798/AlertSuppressionExample.go b/go/ql/test/query-tests/Security/CWE-798/AlertSuppressionExample.go index c6cd369394fd..938884f98df0 100644 --- a/go/ql/test/query-tests/Security/CWE-798/AlertSuppressionExample.go +++ b/go/ql/test/query-tests/Security/CWE-798/AlertSuppressionExample.go @@ -8,7 +8,7 @@ func login(user, password string) bool { func TestLogin(t *testing.T) { user := "testuser" - password := "horsebatterystaplecorrect" // lgtm[go/hardcoded-credentials] + password := "horsebatterystaplecorrect" // $ Alert // lgtm[go/hardcoded-credentials] if !login(user, password) { t.Errorf("Login test failed.") } diff --git a/go/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.go b/go/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.go index 78d0603c2c3c..8c3a96c941b6 100644 --- a/go/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.go +++ b/go/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.go @@ -7,7 +7,7 @@ import ( const ( user = "dbuser" - password = "s3cretp4ssword" + password = "s3cretp4ssword" // $ Alert ) func connect() *sql.DB { diff --git a/go/ql/test/query-tests/Security/CWE-798/HardcodedKeysBad.go b/go/ql/test/query-tests/Security/CWE-798/HardcodedKeysBad.go index 2ffc46147f6e..1c91a2b97b5c 100644 --- a/go/ql/test/query-tests/Security/CWE-798/HardcodedKeysBad.go +++ b/go/ql/test/query-tests/Security/CWE-798/HardcodedKeysBad.go @@ -16,5 +16,5 @@ func bad() (interface{}, error) { } token := jwt.NewWithClaims(nil, claims) - return token.SignedString(mySigningKey) + return token.SignedString(mySigningKey) // $ Alert } diff --git a/go/ql/test/query-tests/Security/CWE-798/jwt.go b/go/ql/test/query-tests/Security/CWE-798/jwt.go index 560f95800df8..f43749e6b4aa 100644 --- a/go/ql/test/query-tests/Security/CWE-798/jwt.go +++ b/go/ql/test/query-tests/Security/CWE-798/jwt.go @@ -39,14 +39,14 @@ func gjwtt() (interface{}, error) { } token := gjwt.NewWithClaims(nil, claims) - return token.SignedString(mySigningKey) // BAD + return token.SignedString(mySigningKey) // $ Alert // BAD } func gin_jwt() (interface{}, error) { var identityKey = "id" return jwt.New(&jwt.GinJWTMiddleware{ Realm: "test zone", - Key: []byte("key2"), // BAD + Key: []byte("key2"), // $ Alert // BAD Timeout: time.Hour, MaxRefresh: time.Hour, IdentityKey: identityKey, @@ -65,12 +65,12 @@ func gin_jwt() (interface{}, error) { func cristalhq() (interface{}, error) { key := []byte(`key3`) - return cristal.NewSignerHS(cristal.HS256, key) // BAD + return cristal.NewSignerHS(cristal.HS256, key) // $ Alert // BAD } func josev3() (interface{}, error) { key := []byte("key4") - return jose_v3.NewSigner(jose_v3.SigningKey{Algorithm: "", Key: key}, nil) // BAD + return jose_v3.NewSigner(jose_v3.SigningKey{Algorithm: "", Key: key}, nil) // $ Alert // BAD } func josev3_2() (interface{}, error) { key2 := []byte("key5") @@ -78,7 +78,7 @@ func josev3_2() (interface{}, error) { "", jose_v3.Recipient{ Algorithm: "", - Key: key2, // BAD + Key: key2, // $ Alert // BAD }, nil) } @@ -88,14 +88,14 @@ func josev2() (interface{}, error) { return jose_v2.NewEncrypter( "", - jose_v2.Recipient{Algorithm: "", Key: key}, // BAD + jose_v2.Recipient{Algorithm: "", Key: key}, // $ Alert // BAD nil, ) } func jose_v2_2() (interface{}, error) { key2 := []byte("key7") - return jose_v2.NewSigner(jose_v2.SigningKey{Algorithm: "", Key: key2}, nil) // BAD + return jose_v2.NewSigner(jose_v2.SigningKey{Algorithm: "", Key: key2}, nil) // $ Alert // BAD } func go_kit() interface{} { @@ -106,24 +106,24 @@ func go_kit() interface{} { mapClaims = gjwt.MapClaims{"user": "go-kit"} ) - return gokit.NewSigner(kid, key, nil, mapClaims) // BAD + return gokit.NewSigner(kid, key, nil, mapClaims) // $ Alert // BAD } func lejwt() (interface{}, error) { sharedKey := []byte("key9") - return le.New(sharedKey) // BAD + return le.New(sharedKey) // $ Alert // BAD } var sharedKeyglobal = []byte("key10") func lejwt2() (interface{}, error) { - return le.New(sharedKeyglobal) // BAD + return le.New(sharedKeyglobal) // $ Alert // BAD } func gogfjwt() interface{} { return &gogf.GfJWTMiddleware{ Realm: "test zone", - Key: []byte("key11"), // BAD + Key: []byte("key11"), // $ Alert // BAD Timeout: time.Minute * 5, MaxRefresh: time.Minute * 5, IdentityKey: "id", @@ -140,7 +140,7 @@ func gogfjwt() interface{} { func irisjwt() interface{} { key := []byte("key12") token := iris.NewTokenWithClaims(nil, nil) - tokenString, _ := token.SignedString(key) // BAD + tokenString, _ := token.SignedString(key) // $ Alert // BAD return tokenString } @@ -149,7 +149,7 @@ func iris12jwt2() interface{} { s := &iris12.Signer{ Alg: nil, - Key: key, // BAD + Key: key, // $ Alert // BAD MaxAge: 3 * time.Second, } return s @@ -157,31 +157,31 @@ func iris12jwt2() interface{} { func irisjwt3() interface{} { key := []byte("key14") - signer := iris12.NewSigner(nil, key, 3*time.Second) // BAD + signer := iris12.NewSigner(nil, key, 3*time.Second) // $ Alert // BAD return signer } func katarasJwt() interface{} { key := []byte("key15") - token, _ := kataras.Sign(nil, key, nil, nil) // BAD + token, _ := kataras.Sign(nil, key, nil, nil) // $ Alert // BAD return token } func katarasJwt2() interface{} { key := []byte("key16") - token, _ := kataras.SignEncrypted(nil, key, nil, nil) // BAD + token, _ := kataras.SignEncrypted(nil, key, nil, nil) // $ Alert // BAD return token } func katarasJwt3() interface{} { key := []byte("key17") - token, _ := kataras.SignEncryptedWithHeader(nil, key, nil, nil, nil) // BAD + token, _ := kataras.SignEncryptedWithHeader(nil, key, nil, nil, nil) // $ Alert // BAD return token } func katarasJwt4() interface{} { key := []byte("key18") - token, _ := kataras.SignWithHeader(nil, key, nil, nil) // BAD + token, _ := kataras.SignWithHeader(nil, key, nil, nil) // $ Alert // BAD return token } @@ -189,5 +189,5 @@ func katarasJwt5() { key := []byte("key19") var keys kataras.Keys var alg kataras.Alg - keys.Register(alg, "api", nil, key) // BAD + keys.Register(alg, "api", nil, key) // $ Alert // BAD } diff --git a/go/ql/test/query-tests/Security/CWE-798/main.go b/go/ql/test/query-tests/Security/CWE-798/main.go index 366933c76934..7934c0d842fd 100644 --- a/go/ql/test/query-tests/Security/CWE-798/main.go +++ b/go/ql/test/query-tests/Security/CWE-798/main.go @@ -3,7 +3,7 @@ package main import "fmt" const ( - passwd = "p4ssw0rd" // NOT OK + passwd = "p4ssw0rd" // $ Alert // NOT OK _password = "" // OK ) diff --git a/go/ql/test/query-tests/Security/CWE-798/sanitizer.go b/go/ql/test/query-tests/Security/CWE-798/sanitizer.go index 749642ceb3bf..19cd3313987e 100644 --- a/go/ql/test/query-tests/Security/CWE-798/sanitizer.go +++ b/go/ql/test/query-tests/Security/CWE-798/sanitizer.go @@ -15,7 +15,7 @@ import ( func check_ok() (interface{}, error) { key := []byte(`some_key`) - return cristal.NewSignerHS(cristal.HS256, key) // BAD + return cristal.NewSignerHS(cristal.HS256, key) // $ Alert // BAD } func GenerateRandomString(size int) string {